2024 年高教社杯全国大学生数学建模竞赛B题入口:
2024 年高教社杯全国大学生数学建模竞赛B题 - 飞书云文档 (feishu.cn)
注:全部代码在本文的附录中。
一:问题1
情形1
先来计算进行假设检验时所需的最小样本量。
导入必要的库
import scipy.stats as stats
import math
scipy.stats
是一个统计相关的库,这里用于获取标准正态分布的分位数(ppf)。math
是Python的标准数学库,这里用于进行数学运算。
定义计算所需样本量的函数
def required_sample_size(alpha, beta, p0):
alpha
是第一类错误(弃真错误)的概率,即错误地拒绝了真实的零假设。beta
是第二类错误(取伪错误)的概率,即错误地接受了错误的零假设。p0
是零假设下的比例或概率,在这个例子中,是供应商声称的次品率。
计算分位数
z_alpha = stats.norm.ppf(1 - alpha) # 对应 95% 置信水平
z_beta = stats.norm.ppf(1 - beta) # 对应 5% 的检验功效
stats.norm.ppf
是正态分布的百分位点函数(percent-point function),用于找到给定累积概率下的z值。1 - alpha
是置信水平,所以z_alpha
对应于95%置信水平下的z值(因为alpha = 0.05
)。1 - beta
是检验的功效,所以z_beta
对应于5%显著性水平下的z值(因为beta = 0.05
)。
计算样本量
n = (z_alpha + z_beta) ** 2 * (p0 * (1 - p0)) / (0.025 ** 2)
- 这行代码是根据假设检验的样本量公式计算的,具体来说,是基于两个正态分布均值差异的检验。
(z_alpha + z_beta) ** 2
是与检验的灵敏度和置信度相关的部分。p0 * (1 - p0)
是零假设下比例的方差。0.025 ** 2
是备择假设下的最小可检测差异的平方,这里假设了次品率差0.025。次品率差是希望能够检测的次品率的最小变化。例如,如果供应商声称的次品率为 10%,通过次品率差这个参数设定,则希望能够在实际的次品率为12.5%时仍然能够显著区分出次品率的变化。
返回样本量
return math.ceil(n)
- 使用
math.ceil
函数将计算得到的样本量n向上取整,因为样本量必须是整数。
设置参数并计算样本量
alpha = 0.05 # 置信水平
beta = 0.05 # 检验功效
p0 = 0.10 # 供应商声称的次品率
sample_size = required_sample_size(alpha, beta, p0)
- 设置了三个参数:置信水平、检验功效和供应商声称的次品率。
- 调用函数计算所需的样本量。
输出结果
print(f"建议的最小抽样检测次数为: {sample_size}")
得出在给定的置信水平和检验功效下,计算检测供应商声称的次品率是否合理所需的最小样本量为1559。如果实际的次品率与供应商声称的次品率有显著差异,该样本量可以确保以一定的概率(1-β)检测出这种差异。
然后举一个利用该抽样策略根据抽样检测结果决定是否拒绝供应商声称的次品率(原假设)。
定义决定是否拒绝原假设的函数
def reject_hypothesis(sample_size, defects_count):
sample_size
是抽样检测的样本量。defects_count
是在样本中检测到的次品数量。
计算样本次品率
p_hat = defects_count / sample_size
p_hat
是样本次品率,即检测到的次品数量除以样本量。
计算检验统计量
z = (p_hat - p0) / math.sqrt((p0 * (1 - p0)) / sample_size)
p0
是原假设下的次品率,即供应商声称的次品率。(p_hat - p0)
是样本次品率与原假设次品率的差值。math.sqrt((p0 * (1 - p0)) / sample_size)
是标准误差,用于将差值标准化。z
是检验统计量,它表示样本次品率与原假设次品率差异的标准正态分布得分。
判断是否拒绝原假设
if z > stats.norm.ppf(1 - alpha):
return True # 拒绝原假设
else:
return False # 不拒绝原假设
stats.norm.ppf(1 - alpha)
是对应于置信水平(1 - alpha)的标准正态分布的临界值。- 如果计算得到的
z
值大于这个临界值,说明样本次品率与原假设的次品率差异显著,因此我们拒绝原假设。- 如果
z
值不大于临界值,我们不能拒绝原假设。
# 示例
defects_count = 30 # 假设从样本中检测到的次品数量
rejected = reject_hypothesis(sample_size, defects_count)
if rejected:
print("拒收这批零配件,因为次品率超过10%")
else:
print("接收这批零配件,次品率在允许范围内")
得出当从1559个商品中检测到30个次品数量,可以“接收这批零配件,次品率在允许范围内”的结论
情形2
与情形1类似,计算进行假设检验时所需的最小样本量。
导入库
import scipy.stats as stats
import math
函数定义部分
def required_sample_size(alpha, p0, delta):
required_sample_size
是一个函数,用来计算所需样本量。alpha
是显著性水平,即犯第一类错误(弃真错误)的最大概率。p0
是原假设中的次品率或成功率。delta
是效应量,即我们希望检测到的最小的次品率差异。
函数内部计算
z_alpha = stats.norm.ppf(1 - alpha)
stats.norm.ppf
是正态分布的分位数函数(percent point function),用于查找给定累积概率下的Z值。1 - alpha
表示我们希望得到的置信水平,例如,如果alpha
是 0.10,则置信水平是 90%。- 因此,
z_alpha
是对应于90%置信水平的Z值,这个值用于确定拒绝域的边界。
n = (z_alpha ** 2 * p0 * (1 - p0)) / (delta ** 2)
- 这行代码是计算所需样本量的公式。
return math.ceil(n)
math.ceil
是向上取整函数,因为样本量必须是整数,所以这里将计算得到的样本量向上取整,确保样本量足够。
参数设置和计算
alpha = 0.10
p0 = 0.10
delta = 0.025
- 设置显著性水平为 10%,声称的次品率为 10%,最小可检测次品率差为 2.5%。
sample_size = required_sample_size(alpha, p0, delta)
- 调用函数计算所需样本量。
print(f"建议的最小抽样检测次数为: {sample_size}")
- 打印出计算得到的建议最小抽样检测次数为237。
总的目的是为了在给定的置信水平、声称的次品率和最小可检测效应量的情况下,计算出进行假设检验所需的最小样本量。
然后继续举一个利用该抽样策略根据抽样检测结果决定是否拒绝供应商声称的次品率(原假设)。主要目的是判断一批零配件的次品率是否超过了预定的可接受水平(在这里是10%)。
计算样本比例 p_hat
p_hat = defects_count / sample_size
这一行计算了样本中次品的比例,即次品数量除以样本总数。
计算z值
z = (p_hat - p0) / math.sqrt((p0 * (1 - p0)) / sample_size)
这里计算了z统计量,用于进行假设检验。
p0
是原假设下的次品率(在这里是0.10,即10%),math.sqrt((p0 * (1 - p0)) / sample_size)
是标准误差。z值表示样本比例与原假设下的比例之间的标准化差异。
判断是否拒绝原假设
if z > stats.norm.ppf(1 - alpha):
return True
else:
return False
这里使用了正态分布的累积分布函数(CDF)的逆函数
stats.norm.ppf
来找到对应于给定的显著性水平alpha
的z值。如果计算出的z值大于这个临界值,则意味着样本数据足够异常,以至于应该拒绝原假设。alpha
是预先设定的显著性水平,通常取0.05,表示5%的犯错风险。
示例使用
# 示例
defects_count = 30 # 假设从样本中检测到的次品数量
rejected = reject_hypothesis(sample_size, defects_count)
if rejected:
print("拒绝这批零配件,因为次品率超过10%")
else:
print("接收这批零配件,次品率在允许范围内")
在示例中,代码设置了次品数量 defects_count
为30,并调用了 reject_hypothesis
函数来判断是否应该拒绝原假设。
- 如果函数返回
True
,则表示应该拒绝原假设,即次品率超过了10%,代码将打印“拒绝这批零配件,因为次品率超过10%”。- 如果函数返回
False
,则表示没有足够证据拒绝原假设,即次品率在可接受范围内,代码将打印“接收这批零配件,次品率在允许范围内”。
得出当从237个商品中检测到30个次品数量,可以“接收这批零配件,次品率在允许范围内”的结论。
二:问题2
首先我将表1整理成了一个Excel表格,可以在本文开头入口获取。
先读取Excel表中的内容:
import pandas as pd
# 读取文件
excel_file = pd.ExcelFile('表1.xlsx')
# 获取所有表名
sheet_names = excel_file.sheet_names
然后分别计算每种情形下检测零配件1节约成本,检测零配件2节约成本,不检测零配件2成本,检测成品节约成本以及拆解不合格成品节约成本。若相应的节约成本大于0,说明该决策可行。
# 计算每种情况的成本
df['零配件1检测成本'] = df['次品率 '] * df['检测成本']
df['零配件2检测成本'] = df['次品率 .1'] * df['检测成本.1']
df['成品检测成本'] = df['次品率 .2'] * df['检测成本.2']
df['不合格成品成本'] = df['次品率 .2'] * df['市场售价']
df['调换损失成本'] = df[' 调换损失'] * df['次品率 .2']
df['拆解费用成本'] = df[' 拆解费用'] * df['次品率 .2']
# 计算总成本
df['总成本'] = df['零配件1检测成本'] + df['零配件2检测成本'] + df['成品检测成本'] + df['不合格成品成本'] + df['调换损失成本'] + df['拆解费用成本']
# 计算不检测零配件1的成本
df['不检测零配件1成本'] = df['次品率 '] * df['购买单价'] + df['成品检测成本'] + df['不合格成品成本'] + df['调换损失成本'] + df['拆解费用成本']
# 计算不检测零配件2的成本
df['不检测零配件2成本'] = df['次品率 .1'] * df['购买单价.1'] + df['成品检测成本'] + df['不合格成品成本'] + df['调换损失成本'] + df['拆解费用成本']
# 计算不检测成品的成本
df['不检测成品成本'] = df['次品率 .2'] * df['市场售价'] + df['调换损失成本']
# 计算不拆解不合格成品的成本
df['不拆解不合格成品成本'] = df['次品率 .2'] * df['市场售价'] + df['调换损失成本']
# 计算每种情况的成本节约
df['检测零配件1节约成本'] = df['不检测零配件1成本'] - df['总成本']
df['检测零配件2节约成本'] = df['不检测零配件2成本'] - df['总成本']
df['检测成品节约成本'] = df['不检测成品成本'] - df['总成本']
df['拆解不合格成品节约成本'] = df['不拆解不合格成品成本'] - df['总成本']
# 制定决策
df['检测零配件1决策'] = df['检测零配件1节约成本'] > 0
df['检测零配件2决策'] = df['检测零配件2节约成本'] > 0
df['检测成品决策'] = df['检测成品节约成本'] > 0
df['拆解不合格成品决策'] = df['拆解不合格成品节约成本'] > 0
# 输出结果
df[['检测零配件1决策', '检测零配件2决策', '检测成品决策', '拆解不合格成品决策']]
根据输出结果,我已经为企业生产过程的各个阶段作出了决策,具体决策如下:
检测零配件 1 决策 | 检测零配件 2 决策 | 检测成品决策 | 拆解不合格成品决策 |
---|---|---|---|
False | True | False | False |
False | True | False | False |
False | True | False | False |
True | True | False | False |
False | True | False | False |
False | True | False | False |
决策结果解释:
检测零配件1决策
:表示是否对零配件 1 进行检测,如果为 True,则表示需要检测,否则表示不需要检测。检测零配件2决策
:表示是否对零配件 2 进行检测,如果为 True,则表示需要检测,否则表示不需要检测。检测成品决策
:表示是否对成品进行检测,如果为 True,则表示需要检测,否则表示不需要检测。拆解不合格成品决策
:表示是否对不合格成品进行拆解,如果为 True,则表示需要拆解,否则表示不需要拆解。
三:附录(代码)
问题1(1)
import scipy.stats as stats
import math
# 计算所需样本量
def required_sample_size(alpha, beta, p0):
z_alpha = stats.norm.ppf(1 - alpha) # 对应 95% 置信水平
z_beta = stats.norm.ppf(1 - beta) # 对应 5% 的检验功效
n = (z_alpha + z_beta) ** 2 * (p0 * (1 - p0)) / (0.025 ** 2) # 使用次品率差0.05作为最小可差异
return math.ceil(n)
# 设置参数
alpha = 0.05 # 置信水平
beta = 0.05 # 检验功效
p0 = 0.10 # 供应商声称的次品率
# 计算所需样本量
sample_size = required_sample_size(alpha, beta, p0)
print(f"建议的最小抽样检测次数为: {sample_size}")
# 假设抽样结果
# 这里假设抽样结果是通过具体抽样检测获得的,k 为次品数量
def reject_hypothesis(sample_size, defects_count):
p_hat = defects_count / sample_size
z = (p_hat - p0) / math.sqrt((p0 * (1 - p0)) / sample_size)
if z > stats.norm.ppf(1 - alpha):
return True # 拒绝原假设
else:
return False # 不拒绝原假设
# 示例
defects_count = 30 # 假设从样本中检测到的次品数量
rejected = reject_hypothesis(sample_size, defects_count)
if rejected:
print("拒收这批零配件,因为次品率超过10%")
else:
print("接收这批零配件,次品率在允许范围内")
问题1(2)
import scipy.stats as stats
import math
# 计算所需样本量
def required_sample_size(alpha, p0, delta):
z_alpha = stats.norm.ppf(1 - alpha) # 对应 90% 置信水平
n = (z_alpha ** 2 * p0 * (1 - p0)) / (delta ** 2) # delta 为最小可检测次品率差
return math.ceil(n)
# 设置参数
alpha = 0.10 # 90% 置信水平的显著性水平
p0 = 0.10 # 声称的次品率
delta = 0.025 # 根据需求选择最小探测次品率差
# 计算所需样本量
sample_size = required_sample_size(alpha, p0, delta)
print(f"建议的最小抽样检测次数为: {sample_size}")
# 假设抽样结果
def reject_hypothesis(sample_size, defects_count):
p_hat = defects_count / sample_size # 计算样本比例
z = (p_hat - p0) / math.sqrt((p0 * (1 - p0)) / sample_size) # 计算z值
if z > stats.norm.ppf(1 - alpha):
return True # 拒绝原假设
else:
return False # 不拒绝原假设
# 示例
defects_count = 30 # 假设从样本中检测到的次品数量
rejected = reject_hypothesis(sample_size, defects_count)
if rejected:
print("拒绝这批零配件,因为次品率超过10%")
else:
print("接收这批零配件,次品率在允许范围内")
问题2
import pandas as pd
# 读取文件
excel_file = pd.ExcelFile('表1.xlsx')
# 获取所有表名
sheet_names = excel_file.sheet_names
# 计算每种情况的成本
df['零配件1检测成本'] = df['次品率 '] * df['检测成本']
df['零配件2检测成本'] = df['次品率 .1'] * df['检测成本.1']
df['成品检测成本'] = df['次品率 .2'] * df['检测成本.2']
df['不合格成品成本'] = df['次品率 .2'] * df['市场售价']
df['调换损失成本'] = df[' 调换损失'] * df['次品率 .2']
df['拆解费用成本'] = df[' 拆解费用'] * df['次品率 .2']
# 计算总成本
df['总成本'] = df['零配件1检测成本'] + df['零配件2检测成本'] + df['成品检测成本'] + df['不合格成品成本'] + df['调换损失成本'] + df['拆解费用成本']
# 计算不检测零配件1的成本
df['不检测零配件1成本'] = df['次品率 '] * df['购买单价'] + df['成品检测成本'] + df['不合格成品成本'] + df['调换损失成本'] + df['拆解费用成本']
# 计算不检测零配件2的成本
df['不检测零配件2成本'] = df['次品率 .1'] * df['购买单价.1'] + df['成品检测成本'] + df['不合格成品成本'] + df['调换损失成本'] + df['拆解费用成本']
# 计算不检测成品的成本
df['不检测成品成本'] = df['次品率 .2'] * df['市场售价'] + df['调换损失成本']
# 计算不拆解不合格成品的成本
df['不拆解不合格成品成本'] = df['次品率 .2'] * df['市场售价'] + df['调换损失成本']
# 计算每种情况的成本节约
df['检测零配件1节约成本'] = df['不检测零配件1成本'] - df['总成本']
df['检测零配件2节约成本'] = df['不检测零配件2成本'] - df['总成本']
df['检测成品节约成本'] = df['不检测成品成本'] - df['总成本']
df['拆解不合格成品节约成本'] = df['不拆解不合格成品成本'] - df['总成本']
# 制定决策
df['检测零配件1决策'] = df['检测零配件1节约成本'] > 0
df['检测零配件2决策'] = df['检测零配件2节约成本'] > 0
df['检测成品决策'] = df['检测成品节约成本'] > 0
df['拆解不合格成品决策'] = df['拆解不合格成品节约成本'] > 0
# 输出结果
df[['检测零配件1决策', '检测零配件2决策', '检测成品决策', '拆解不合格成品决策']]
四:每日股票行情数据
想要探索更多元化的数据分析视角,可以关注之前发布的相关内容。