查看全课大纲(第 42 / 51 节)
  1. 1.为什么人人都该学点编程?
  2. 2.计算机与程序设计:你的电脑到底在“想”什么?
  3. 3.Python 这门语言,到底有什么魔力?
  4. 4.Python 开发环境配置:如何拥有你的第一个“编程工具箱”?
  5. 5.如何安装一个更强大的代码编辑器?
  6. 6.汇率兑换1.0:你的第一个“钱生钱”小程序
  7. 7.你的第一行代码,藏着哪些秘密?
  8. 8.汇率兑换2.0(上):让程序看懂“CNY”和“USD”
  9. 9.汇率兑换程序,如何让它“聪明”地判断币种?
  10. 10.汇率兑换程序能一直运行,直到我喊停吗?
  11. 11.汇率兑换4.0:如何把“算钱”功能打包成积木?
  12. 12.汇率兑换5.0:给你的程序穿上“结构化”的西装
  13. 13.怎么用 Python 画一个会动的五角星?
  14. 14.如何让程序自动画出不同大小的五角星?
  15. 15.函数自己调用自己,会发生什么?
  16. 16.用递归画出神奇的分形树
  17. 17.Python 怎么计算你一天躺着不动能消耗多少热量?
  18. 18.如何让程序“活”起来,持续为你服务?
  19. 19.如何让 BMR 计算器更“聪明”?
  20. 20.当程序遇到“不按套路出牌”的用户怎么办?
  21. 21.怎么用 Python 模拟一个“滚雪球”式的存钱计划?
  22. 22.如何用列表记录每一周的存款?
  23. 23.如何让程序自己数数?—— 用 for 循环解放你的双手
  24. 24.52周存钱挑战4.0:你的存款计算器能有多灵活?
  25. 25.52周存钱挑战:怎么根据日期自动查存款?
  26. 26.Python 怎么判断一年中的第几天?
  27. 27.列表 vs 元组:哪个更适合存储月份天数?
  28. 28.用集合给月份分个队,换个思路算天数
  29. 29.把月份和天数“锁”在一起:用字典给数据配个对
  30. 30.Python 怎么判断密码强弱?
  31. 31.Python 怎么给密码设置“防沉迷”系统?
  32. 32.Python 怎么把密码保存到文件里?
  33. 33.Python 怎么读取文件里的密码?
  34. 34.Python 怎么把密码检查工具“打包”起来?
  35. 35.Python 怎么把文件操作也“打包”起来?
  36. 36.计算机怎么“扔骰子”?——用Python模拟随机事件
  37. 37.如何用 Python 模拟掷两个骰子?
  38. 38.怎么用 Python 把骰子轨迹画出来?
  39. 39.骰子点数分布长啥样?用直方图一眼看穿!
  40. 40.用科学计算库让骰子程序“起飞”
  41. 41.空气质量指数怎么算?手把手教你写一个AQI计算器
  42. 42.空气质量指数计算:从零开始,让程序看懂空气
  43. 43.如何读取空气质量数据文件并找出空气质量最好的五个监测点?
  44. 44.JSON 数据怎么变成 Excel 表格?—— 让数据换个“马甲”
  45. 45.Python 怎么让程序自己判断文件类型?
  46. 46.如何让程序自己上网查空气质量?
  47. 47.用美味的汤来解析网页:Beautiful Soup 入门
  48. 48.如何让爬虫自动抓取全国所有城市的空气质量?
  49. 49.爬到的数据怎么存下来?—— 把全国空气质量数据保存为CSV文件
  50. 50.用 pandas 玩转空气质量数据:找出全国空气最好和最差的城市
  51. 51.空气质量数据怎么“洗”干净,还能画成图?

空气质量指数计算:从零开始,让程序看懂空气

约 7 分钟

小象实战讲义 · Python 入门:8 个小项目边玩边学

想知道你所在城市的空气质量到底怎么样吗?天气预报里那个“AQI”数字是怎么算出来的?今天,我们就来亲手打造一个空气质量指数计算器!学完这一节,你就能输入PM2.5、一氧化碳等污染物的浓度,让程序自动算出对应的空气质量指数(AQI),就像给空气做一次“体检评分”。

💡 核心导读

  • 核心任务:实现一个空气质量指数(AQI)计算程序。
  • 核心原理:AQI是通过“线性缩放”公式,将污染物浓度转换成一个0-500之间的指数。
  • 本节新增:学会分段判断和封装通用计算函数,让代码更清晰、更易维护。
  • 你将得到:一个能处理PM2.5和一氧化碳(CO)的简易AQI计算器。

空气质量指数:给空气“打分”的规则

空气质量指数(AQI)不是一个简单的测量值,而是一个根据多种污染物浓度,通过一套国家标准计算出来的综合指数。它把复杂的浓度数据,转换成一个我们容易理解的0到500的数字,并对应“优”、“良”、“轻度污染”等等级。

计算AQI的关键在于先计算每种污染物的空气质量分指数(IAQI)。每种污染物(如PM2.5、PM10、CO等)都有一张对应的浓度限值表。我们的任务就是:根据测量到的浓度值,找到它属于哪个浓度区间,然后用一个公式把它“映射”到对应的IAQI区间。

这个映射公式就是一个线性缩放公式:

IAQI = (IAQI_高 - IAQI_低) × (Cp - BP_低) / (BP_高 - BP_低) + IAQI_低

别被公式吓到!我们把它拆开看:

  • Cp:我们测量到的污染物浓度值(比如PM2.5是55微克/立方米)。
  • [BP_低, BP_高]:浓度值Cp所在的国家标准浓度区间。
  • [IAQI_低, IAQI_高]:上面那个浓度区间对应的IAQI指数区间。

这个公式就像一把比例尺:它把一段浓度范围,按比例拉伸或压缩到另一段指数范围。我们接下来要做的,就是把这张“比例尺”用代码实现。

第一步:打造万能“比例尺”——线性缩放函数

既然每种污染物都要用同一个公式,我们何不先把这个公式做成一个“工具函数”呢?这样以后每次计算,直接“调用工具”就行了,不用重复写公式。

def cal_linear(iaqi_lo, iaqi_hi, bp_lo, bp_hi, cp):
    """
    线性缩放函数(万能比例尺)
    参数:
        iaqi_lo: IAQI指数区间下限
        iaqi_hi: IAQI指数区间上限
        bp_lo:  污染物浓度区间下限
        bp_hi:  污染物浓度区间上限
        cp:     实测污染物浓度
    返回:
        计算出的IAQI值
    """
    iaqi = (iaqi_hi - iaqi_lo) * (cp - bp_lo) / (bp_hi - bp_lo) + iaqi_lo
    return iaqi

# 我们来测试一下这把"尺子"准不准
# 假设PM2.5浓度是55,属于[35, 75]浓度区间,对应IAQI区间[50, 100]
test_iaqi = cal_linear(50, 100, 35, 75, 55)
print(f"PM2.5浓度为55时,计算出的IAQI分指数为:{test_iaqi}")
PM2.5浓度为55时,计算出的IAQI分指数为:75.0

看,我们得到了75。这意味着当PM2.5为55时,它的“分指数”是75(在 [50,100] 区间内按比例:50 + 50×(55−35)/(75−35) = 75)。这个函数就是我们后续所有计算的基础工具。

第二步:为PM2.5定制计算器

有了万能“比例尺”,我们还需要知道具体怎么用。对于PM2.5,国家标准规定了多个浓度区间。我们需要写一个函数,根据输入的PM2.5浓度值,判断它落在哪个区间,然后调用正确的“比例尺”参数。

这就是分段判断,我们用 if ... elif ... else 来实现。

def cal_linear(iaqi_lo, iaqi_hi, bp_lo, bp_hi, cp):
    """
    线性缩放函数(万能比例尺)
    参数:
        iaqi_lo: IAQI指数区间下限
        iaqi_hi: IAQI指数区间上限
        bp_lo:  污染物浓度区间下限
        bp_hi:  污染物浓度区间上限
        cp:     实测污染物浓度
    返回:
        计算出的IAQI值
    """
    iaqi = (iaqi_hi - iaqi_lo) * (cp - bp_lo) / (bp_hi - bp_lo) + iaqi_lo
    return iaqi

# 我们来测试一下这把"尺子"准不准
# 假设PM2.5浓度是55,属于[35, 75]浓度区间,对应IAQI区间[50, 100]
test_iaqi = cal_linear(50, 100, 35, 75, 55)
print(f"PM2.5浓度为55时,计算出的IAQI分指数为:{test_iaqi}")


def cal_pm_iaqi(pm_val):
    """
    计算PM2.5的IAQI分指数
    参数:
        pm_val: PM2.5的浓度值(微克/立方米)
    返回:
        PM2.5的IAQI值
    """
    if 0 <= pm_val < 36:
        # 浓度在0-35之间,IAQI对应0-50
        iaqi = cal_linear(0, 50, 0, 35, pm_val)
    elif 36 <= pm_val < 76:
        # 浓度在36-75之间,IAQI对应50-100
        iaqi = cal_linear(50, 100, 35, 75, pm_val)
    elif 76 <= pm_val < 116:
        # 浓度在76-115之间,IAQI对应100-150
        iaqi = cal_linear(100, 150, 75, 115, pm_val)
    else:
        # 为了示例简化,更高浓度我们先跳过
        print("浓度值超过当前计算范围")
        iaqi = None
    return iaqi

# 测试几个值
print(f"PM2.5为20时,IAQI: {cal_pm_iaqi(20)}")
print(f"PM2.5为55时,IAQI: {cal_pm_iaqi(55)}")
print(f"PM2.5为100时,IAQI: {cal_pm_iaqi(100)}")
PM2.5浓度为55时,计算出的IAQI分指数为:75.0
PM2.5为20时,IAQI: 28.571428571428573
PM2.5为55时,IAQI: 75.0
PM2.5为100时,IAQI: 131.25
def cal_linear(iaqi_lo, iaqi_hi, bp_lo, bp_hi, cp):
    """
    线性缩放函数(万能比例尺)
    参数:
        iaqi_lo: IAQI指数区间下限
        iaqi_hi: IAQI指数区间上限
        bp_lo:  污染物浓度区间下限
        bp_hi:  污染物浓度区间上限
        cp:     实测污染物浓度
    返回:
        计算出的IAQI值
    """
    iaqi = (iaqi_hi - iaqi_lo) * (cp - bp_lo) / (bp_hi - bp_lo) + iaqi_lo
    return iaqi

# 我们来测试一下这把"尺子"准不准
# 假设PM2.5浓度是55,属于[35, 75]浓度区间,对应IAQI区间[50, 100]
test_iaqi = cal_linear(50, 100, 35, 75, 55)
print(f"PM2.5浓度为55时,计算出的IAQI分指数为:{test_iaqi}")


def cal_pm_iaqi(pm_val):
    """
    计算PM2.5的IAQI分指数
    参数:
        pm_val: PM2.5的浓度值(微克/立方米)
    返回:
        PM2.5的IAQI值
    """
    if 0 <= pm_val < 36:
        # 浓度在0-35之间,IAQI对应0-50
        iaqi = cal_linear(0, 50, 0, 35, pm_val)
    elif 36 <= pm_val < 76:
        # 浓度在36-75之间,IAQI对应50-100
        iaqi = cal_linear(50, 100, 35, 75, pm_val)
    elif 76 <= pm_val < 116:
        # 浓度在76-115之间,IAQI对应100-150
        iaqi = cal_linear(100, 150, 75, 115, pm_val)
    else:
        # 为了示例简化,更高浓度我们先跳过
        print("浓度值超过当前计算范围")
        iaqi = None
    return iaqi

# 测试几个值
print(f"PM2.5为20时,IAQI: {cal_pm_iaqi(20)}")
print(f"PM2.5为55时,IAQI: {cal_pm_iaqi(55)}")
print(f"PM2.5为100时,IAQI: {cal_pm_iaqi(100)}")
PM2.5浓度为55时,计算出的IAQI分指数为:75.0
PM2.5为20时,IAQI: 28.571428571428573
PM2.5为55时,IAQI: 75.0
PM2.5为100时,IAQI: 131.25

看,我们的PM2.5计算器工作了!它就像一个自动查表员,看到浓度值,就去翻国家标准手册,找到对应的区间,然后用我们准备好的“比例尺”算出分数。

第三步:再加入一氧化碳(CO)计算器

空气污染不止PM2.5,还有一氧化碳(CO)、二氧化硫等。计算逻辑完全一样,只是查的表(浓度区间)不同。我们依葫芦画瓢,给CO也做一个。

def cal_linear(iaqi_lo, iaqi_hi, bp_lo, bp_hi, cp):
    """
    线性缩放函数(万能比例尺)
    参数:
        iaqi_lo: IAQI指数区间下限
        iaqi_hi: IAQI指数区间上限
        bp_lo:  污染物浓度区间下限
        bp_hi:  污染物浓度区间上限
        cp:     实测污染物浓度
    返回:
        计算出的IAQI值
    """
    iaqi = (iaqi_hi - iaqi_lo) * (cp - bp_lo) / (bp_hi - bp_lo) + iaqi_lo
    return iaqi

# 我们来测试一下这把"尺子"准不准
# 假设PM2.5浓度是55,属于[35, 75]浓度区间,对应IAQI区间[50, 100]
test_iaqi = cal_linear(50, 100, 35, 75, 55)
print(f"PM2.5浓度为55时,计算出的IAQI分指数为:{test_iaqi}")


def cal_co_iaqi(co_val):
    """
    计算CO(一氧化碳)的IAQI分指数(基于24小时平均浓度,单位:毫克/立方米)
    参数:
        co_val: CO的浓度值
    返回:
        CO的IAQI值
    """
    if 0 <= co_val < 3:
        # 浓度0-2 mg/m³,对应IAQI 0-50
        iaqi = cal_linear(0, 50, 0, 3, co_val)
    elif 3 <= co_val < 5:
        # 浓度3-4 mg/m³,对应IAQI 50-100
        iaqi = cal_linear(50, 100, 2, 4, co_val)
    else:
        # 简化处理
        print("CO浓度值超过当前计算范围")
        iaqi = None
    return iaqi

# 测试CO计算
print(f"CO为1.5时,IAQI: {cal_co_iaqi(1.5)}")
print(f"CO为3.5时,IAQI: {cal_co_iaqi(3.5)}")
PM2.5浓度为55时,计算出的IAQI分指数为:75.0
CO为1.5时,IAQI: 25.0
CO为3.5时,IAQI: 87.5
def cal_linear(iaqi_lo, iaqi_hi, bp_lo, bp_hi, cp):
    """
    线性缩放函数(万能比例尺)
    参数:
        iaqi_lo: IAQI指数区间下限
        iaqi_hi: IAQI指数区间上限
        bp_lo:  污染物浓度区间下限
        bp_hi:  污染物浓度区间上限
        cp:     实测污染物浓度
    返回:
        计算出的IAQI值
    """
    iaqi = (iaqi_hi - iaqi_lo) * (cp - bp_lo) / (bp_hi - bp_lo) + iaqi_lo
    return iaqi

# 我们来测试一下这把"尺子"准不准
# 假设PM2.5浓度是55,属于[35, 75]浓度区间,对应IAQI区间[50, 100]
test_iaqi = cal_linear(50, 100, 35, 75, 55)
print(f"PM2.5浓度为55时,计算出的IAQI分指数为:{test_iaqi}")


def cal_co_iaqi(co_val):
    """
    计算CO(一氧化碳)的IAQI分指数(基于24小时平均浓度,单位:毫克/立方米)
    参数:
        co_val: CO的浓度值
    返回:
        CO的IAQI值
    """
    if 0 <= co_val < 3:
        # 浓度0-2 mg/m³,对应IAQI 0-50
        iaqi = cal_linear(0, 50, 0, 3, co_val)
    elif 3 <= co_val < 5:
        # 浓度3-4 mg/m³,对应IAQI 50-100
        iaqi = cal_linear(50, 100, 2, 4, co_val)
    else:
        # 简化处理
        print("CO浓度值超过当前计算范围")
        iaqi = None
    return iaqi

# 测试CO计算
print(f"CO为1.5时,IAQI: {cal_co_iaqi(1.5)}")
print(f"CO为3.5时,IAQI: {cal_co_iaqi(3.5)}")
PM2.5浓度为55时,计算出的IAQI分指数为:75.0
CO为1.5时,IAQI: 25.0
CO为3.5时,IAQI: 87.5

太棒了!现在我们有了两把“专用计算尺”,一把量PM2.5,一把量CO。

第四步:组装最终AQI计算器

AQI的定义是:所有污染物IAQI分指数中的最大值。也就是说,空气好不好,由“考得最差的那门科目”决定。

所以,我们最终的AQI计算函数需要:

  1. 接收PM2.5和CO的浓度。
  2. 分别调用它们专属的计算器,得到两个IAQI。
  3. 比较这两个数,取出最大的那个,它就是最终的AQI。
def cal_linear(iaqi_lo, iaqi_hi, bp_lo, bp_hi, cp):
    """
    线性缩放函数(万能比例尺)
    参数:
        iaqi_lo: IAQI指数区间下限
        iaqi_hi: IAQI指数区间上限
        bp_lo:  污染物浓度区间下限
        bp_hi:  污染物浓度区间上限
        cp:     实测污染物浓度
    返回:
        计算出的IAQI值
    """
    iaqi = (iaqi_hi - iaqi_lo) * (cp - bp_lo) / (bp_hi - bp_lo) + iaqi_lo
    return iaqi

# 我们来测试一下这把"尺子"准不准
# 假设PM2.5浓度是55,属于[35, 75]浓度区间,对应IAQI区间[50, 100]
test_iaqi = cal_linear(50, 100, 35, 75, 55)
print(f"PM2.5浓度为55时,计算出的IAQI分指数为:{test_iaqi}")

def cal_co_iaqi(co_val):
    """
    计算CO(一氧化碳)的IAQI分指数(基于24小时平均浓度,单位:毫克/立方米)
    参数:
        co_val: CO的浓度值
    返回:
        CO的IAQI值
    """
    if 0 <= co_val < 3:
        # 浓度0-2 mg/m³,对应IAQI 0-50
        iaqi = cal_linear(0, 50, 0, 3, co_val)
    elif 3 <= co_val < 5:
        # 浓度3-4 mg/m³,对应IAQI 50-100
        iaqi = cal_linear(50, 100, 2, 4, co_val)
    else:
        # 简化处理
        print("CO浓度值超过当前计算范围")
        iaqi = None
    return iaqi

# 测试CO计算
print(f"CO为1.5时,IAQI: {cal_co_iaqi(1.5)}")
print(f"CO为3.5时,IAQI: {cal_co_iaqi(3.5)}")


def cal_linear(iaqi_lo, iaqi_hi, bp_lo, bp_hi, cp):
    """
    线性缩放函数(万能比例尺)
    参数:
        iaqi_lo: IAQI指数区间下限
        iaqi_hi: IAQI指数区间上限
        bp_lo:  污染物浓度区间下限
        bp_hi:  污染物浓度区间上限
        cp:     实测污染物浓度
    返回:
        计算出的IAQI值
    """
    iaqi = (iaqi_hi - iaqi_lo) * (cp - bp_lo) / (bp_hi - bp_lo) + iaqi_lo
    return iaqi

# 我们来测试一下这把"尺子"准不准
# 假设PM2.5浓度是55,属于[35, 75]浓度区间,对应IAQI区间[50, 100]
test_iaqi = cal_linear(50, 100, 35, 75, 55)
print(f"PM2.5浓度为55时,计算出的IAQI分指数为:{test_iaqi}")

def cal_pm_iaqi(pm_val):
    """
    计算PM2.5的IAQI分指数
    参数:
        pm_val: PM2.5的浓度值(微克/立方米)
    返回:
        PM2.5的IAQI值
    """
    if 0 <= pm_val < 36:
        # 浓度在0-35之间,IAQI对应0-50
        iaqi = cal_linear(0, 50, 0, 35, pm_val)
    elif 36 <= pm_val < 76:
        # 浓度在36-75之间,IAQI对应50-100
        iaqi = cal_linear(50, 100, 35, 75, pm_val)
    elif 76 <= pm_val < 116:
        # 浓度在76-115之间,IAQI对应100-150
        iaqi = cal_linear(100, 150, 75, 115, pm_val)
    else:
        # 为了示例简化,更高浓度我们先跳过
        print("浓度值超过当前计算范围")
        iaqi = None
    return iaqi

# 测试几个值
print(f"PM2.5为20时,IAQI: {cal_pm_iaqi(20)}")
print(f"PM2.5为55时,IAQI: {cal_pm_iaqi(55)}")
print(f"PM2.5为100时,IAQI: {cal_pm_iaqi(100)}")


def cal_aqi(pm_val, co_val):
    """
    计算最终的AQI指数
    参数:
        pm_val: PM2.5浓度
        co_val: CO浓度
    返回:
        最终的AQI值
    """
    # 1. 计算各污染物的分指数
    pm_iaqi = cal_pm_iaqi(pm_val)
    co_iaqi = cal_co_iaqi(co_val)

    # 2. 将所有分指数放入列表
    iaqi_list = []
    if pm_iaqi is not None:
        iaqi_list.append(pm_iaqi)
    if co_iaqi is not None:
        iaqi_list.append(co_iaqi)

    # 3. AQI等于所有分指数中的最大值
    if iaqi_list: # 确保列表不为空
        aqi = max(iaqi_list)
        return aqi
    else:
        return None

# 来一次完整的空气质量"体检"!
# 假设某地监测到:PM2.5 = 88, CO = 1.2
final_aqi = cal_aqi(88, 1.2)
print(f"当PM2.5为88,CO为1.2时,最终的AQI指数是:{final_aqi}")
PM2.5浓度为55时,计算出的IAQI分指数为:75.0
CO为1.5时,IAQI: 25.0
CO为3.5时,IAQI: 87.5
PM2.5浓度为55时,计算出的IAQI分指数为:75.0
PM2.5为20时,IAQI: 28.571428571428573
PM2.5为55时,IAQI: 75.0
PM2.5为100时,IAQI: 131.25
当PM2.5为88,CO为1.2时,最终的AQI指数是:116.25
def cal_linear(iaqi_lo, iaqi_hi, bp_lo, bp_hi, cp):
    """
    线性缩放函数(万能比例尺)
    参数:
        iaqi_lo: IAQI指数区间下限
        iaqi_hi: IAQI指数区间上限
        bp_lo:  污染物浓度区间下限
        bp_hi:  污染物浓度区间上限
        cp:     实测污染物浓度
    返回:
        计算出的IAQI值
    """
    iaqi = (iaqi_hi - iaqi_lo) * (cp - bp_lo) / (bp_hi - bp_lo) + iaqi_lo
    return iaqi

# 我们来测试一下这把"尺子"准不准
# 假设PM2.5浓度是55,属于[35, 75]浓度区间,对应IAQI区间[50, 100]
test_iaqi = cal_linear(50, 100, 35, 75, 55)
print(f"PM2.5浓度为55时,计算出的IAQI分指数为:{test_iaqi}")

def cal_co_iaqi(co_val):
    """
    计算CO(一氧化碳)的IAQI分指数(基于24小时平均浓度,单位:毫克/立方米)
    参数:
        co_val: CO的浓度值
    返回:
        CO的IAQI值
    """
    if 0 <= co_val < 3:
        # 浓度0-2 mg/m³,对应IAQI 0-50
        iaqi = cal_linear(0, 50, 0, 3, co_val)
    elif 3 <= co_val < 5:
        # 浓度3-4 mg/m³,对应IAQI 50-100
        iaqi = cal_linear(50, 100, 2, 4, co_val)
    else:
        # 简化处理
        print("CO浓度值超过当前计算范围")
        iaqi = None
    return iaqi

# 测试CO计算
print(f"CO为1.5时,IAQI: {cal_co_iaqi(1.5)}")
print(f"CO为3.5时,IAQI: {cal_co_iaqi(3.5)}")


def cal_linear(iaqi_lo, iaqi_hi, bp_lo, bp_hi, cp):
    """
    线性缩放函数(万能比例尺)
    参数:
        iaqi_lo: IAQI指数区间下限
        iaqi_hi: IAQI指数区间上限
        bp_lo:  污染物浓度区间下限
        bp_hi:  污染物浓度区间上限
        cp:     实测污染物浓度
    返回:
        计算出的IAQI值
    """
    iaqi = (iaqi_hi - iaqi_lo) * (cp - bp_lo) / (bp_hi - bp_lo) + iaqi_lo
    return iaqi

# 我们来测试一下这把"尺子"准不准
# 假设PM2.5浓度是55,属于[35, 75]浓度区间,对应IAQI区间[50, 100]
test_iaqi = cal_linear(50, 100, 35, 75, 55)
print(f"PM2.5浓度为55时,计算出的IAQI分指数为:{test_iaqi}")

def cal_pm_iaqi(pm_val):
    """
    计算PM2.5的IAQI分指数
    参数:
        pm_val: PM2.5的浓度值(微克/立方米)
    返回:
        PM2.5的IAQI值
    """
    if 0 <= pm_val < 36:
        # 浓度在0-35之间,IAQI对应0-50
        iaqi = cal_linear(0, 50, 0, 35, pm_val)
    elif 36 <= pm_val < 76:
        # 浓度在36-75之间,IAQI对应50-100
        iaqi = cal_linear(50, 100, 35, 75, pm_val)
    elif 76 <= pm_val < 116:
        # 浓度在76-115之间,IAQI对应100-150
        iaqi = cal_linear(100, 150, 75, 115, pm_val)
    else:
        # 为了示例简化,更高浓度我们先跳过
        print("浓度值超过当前计算范围")
        iaqi = None
    return iaqi

# 测试几个值
print(f"PM2.5为20时,IAQI: {cal_pm_iaqi(20)}")
print(f"PM2.5为55时,IAQI: {cal_pm_iaqi(55)}")
print(f"PM2.5为100时,IAQI: {cal_pm_iaqi(100)}")


def cal_aqi(pm_val, co_val):
    """
    计算最终的AQI指数
    参数:
        pm_val: PM2.5浓度
        co_val: CO浓度
    返回:
        最终的AQI值
    """
    # 1. 计算各污染物的分指数
    pm_iaqi = cal_pm_iaqi(pm_val)
    co_iaqi = cal_co_iaqi(co_val)

    # 2. 将所有分指数放入列表
    iaqi_list = []
    if pm_iaqi is not None:
        iaqi_list.append(pm_iaqi)
    if co_iaqi is not None:
        iaqi_list.append(co_iaqi)

    # 3. AQI等于所有分指数中的最大值
    if iaqi_list: # 确保列表不为空
        aqi = max(iaqi_list)
        return aqi
    else:
        return None

# 来一次完整的空气质量"体检"!
# 假设某地监测到:PM2.5 = 88, CO = 1.2
final_aqi = cal_aqi(88, 1.2)
print(f"当PM2.5为88,CO为1.2时,最终的AQI指数是:{final_aqi}")
PM2.5浓度为55时,计算出的IAQI分指数为:75.0
CO为1.5时,IAQI: 25.0
CO为3.5时,IAQI: 87.5
PM2.5浓度为55时,计算出的IAQI分指数为:75.0
PM2.5为20时,IAQI: 28.571428571428573
PM2.5为55时,IAQI: 75.0
PM2.5为100时,IAQI: 131.25
当PM2.5为88,CO为1.2时,最终的AQI指数是:116.25

恭喜!你的第一个空气质量指数计算器诞生了!输入两个数字,它就能告诉你空气质量的“综合得分”。虽然我们现在只处理了两种污染物,但整个框架已经搭建完成。其他污染物(如PM10、O3等)的计算,只是往这个框架里添加更多的“专用计算尺”而已。

📝 动手练一练

  1. 功能扩展:我们的程序目前只处理了PM2.5和CO。请查阅国家空气质量标准(GB 3095-2012),尝试为二氧化氮(NO2,1小时平均)添加计算函数 cal_no2_iaqi。已知其一个浓度区间为:0-100 µg/m³ 对应 IAQI 0-50。

  2. 交互升级:现在的程序浓度值是写死在代码里的。想象一下,如果让用户自己输入浓度值,程序该怎么改?请描述你的思路(不需要写完整代码,说说关键步骤)。

  3. 理解输出:如果某地PM2.5的IAQI是130,CO的IAQI是85,那么程序最终输出的AQI会是多少?为什么?

👉 点击查看参考答案
  1. 添加NO2计算函数: 思路是模仿 cal_co_iaqi 函数,根据NO2的浓度区间进行判断。关键是要找到正确的浓度上下限和对应的IAQI上下限。
def cal_linear(iaqi_lo, iaqi_hi, bp_lo, bp_hi, cp):
    """
    线性缩放函数(万能比例尺)
    参数:
        iaqi_lo: IAQI指数区间下限
        iaqi_hi: IAQI指数区间上限
        bp_lo:  污染物浓度区间下限
        bp_hi:  污染物浓度区间上限
        cp:     实测污染物浓度
    返回:
        计算出的IAQI值
    """
    iaqi = (iaqi_hi - iaqi_lo) * (cp - bp_lo) / (bp_hi - bp_lo) + iaqi_lo
    return iaqi

# 我们来测试一下这把"尺子"准不准
# 假设PM2.5浓度是55,属于[35, 75]浓度区间,对应IAQI区间[50, 100]
test_iaqi = cal_linear(50, 100, 35, 75, 55)
print(f"PM2.5浓度为55时,计算出的IAQI分指数为:{test_iaqi}")


def cal_no2_iaqi(no2_val):
    """计算NO2(二氧化氮)的IAQI分指数(1小时平均)"""
    if 0 <= no2_val <= 100:
        # 浓度0-100 µg/m³,对应IAQI 0-50
        iaqi = cal_linear(0, 50, 0, 100, no2_val)
    else:
        # 更高区间暂不实现
        print("NO2浓度超过当前计算范围")
        iaqi = None
    return iaqi
# 测试
print(f"NO2为50时,IAQI: {cal_no2_iaqi(50)}") # 应输出25.0
PM2.5浓度为55时,计算出的IAQI分指数为:75.0
NO2为50时,IAQI: 25.0
  1. 交互升级思路:

    • 使用 input() 函数提示用户输入,例如:pm_input = input("请输入PM2.5浓度值: ")。
    • 将获取到的字符串(如"88")用 float() 函数转换为数字类型。
    • 将转换后的值传递给 cal_aqi 函数进行计算。
    • 注意:在实际讲义代码块中,我们会用固定值代替 input() 以保证可运行,但你要知道原理。
  2. 理解输出: 最终AQI会是 130。 因为AQI取的是所有污染物IAQI分指数中的最大值。PM2.5的130分比CO的85分更高(意味着PM2.5污染更严重),所以整体的空气质量指数就以这个更严重的分数为准。

本章小结

今天我们完成了一个非常“接地气”的项目——空气质量指数计算。你不仅学会了AQI的计算原理,更重要的是掌握了两个强大的编程思维:

  1. 抽象与封装:把复杂的线性缩放公式封装成一个通用的 cal_linear 函数,避免了代码重复。
  2. 分而治之:为每种污染物编写独立的计算函数(cal_pm_iaqi, cal_co_iaqi),使程序结构清晰,易于维护和扩展。

你现在已经能让程序理解并处理现实世界中的复杂规则了。从汇率、存钱计划,到现在的空气质量,你的编程技能正在解决越来越多样的实际问题!

📋 行动清单

  • 运行本节所有代码,确保你理解了从浓度到IAQI,再到AQI的整个计算流程。
  • 尝试修改测试数据,用不同的PM2.5和CO浓度值,观察AQI结果如何变化。
  • 挑战一下,根据国家标准,为PM10或臭氧(O3)添加一个新的IAQI计算函数。

—— 小象教研组

配套资料 · 直接下载

课件、代码、数据集等配套资料全部免费,点击即可直接下载,无需分享或解锁。

  • 第9章代码包:空气质量指数计算(含全部版本 10 个 .py)
    ZIP · 64KB
    下载
  • 数据集:aqi.csv(各城市 AQI 长表)
    772B
    下载
  • 数据集:beijing_aqi.json(北京监测点)
    3KB
    下载
  • 数据集:bottom10_aqi.csv(空气质量最差 10 城)
    412B
    下载
  • 数据集:china_city_aqi.csv(全国城市 AQI)
    13KB
    下载
  • 数据集:shanghai_aqi.json(上海监测点)
    3KB
    下载
  • 数据集:top10_aqi.csv(空气质量最好 10 城)
    372B
    下载
  • 数据集:top5_aqi.json(空气质量最好 5 城)
    1007B
    下载
看图文没弄懂?展开看本节视频讲解(约 7 分钟)
📺 正在播放小象学院官方高清录播(支持倍速与清晰度调节)