查看全课大纲(第 39 / 51 节)
- 1.为什么人人都该学点编程?
- 2.计算机与程序设计:你的电脑到底在“想”什么?
- 3.Python 这门语言,到底有什么魔力?
- 4.Python 开发环境配置:如何拥有你的第一个“编程工具箱”?
- 5.如何安装一个更强大的代码编辑器?
- 6.汇率兑换1.0:你的第一个“钱生钱”小程序
- 7.你的第一行代码,藏着哪些秘密?
- 8.汇率兑换2.0(上):让程序看懂“CNY”和“USD”
- 9.汇率兑换程序,如何让它“聪明”地判断币种?
- 10.汇率兑换程序能一直运行,直到我喊停吗?
- 11.汇率兑换4.0:如何把“算钱”功能打包成积木?
- 12.汇率兑换5.0:给你的程序穿上“结构化”的西装
- 13.怎么用 Python 画一个会动的五角星?
- 14.如何让程序自动画出不同大小的五角星?
- 15.函数自己调用自己,会发生什么?
- 16.用递归画出神奇的分形树
- 17.Python 怎么计算你一天躺着不动能消耗多少热量?
- 18.如何让程序“活”起来,持续为你服务?
- 19.如何让 BMR 计算器更“聪明”?
- 20.当程序遇到“不按套路出牌”的用户怎么办?
- 21.怎么用 Python 模拟一个“滚雪球”式的存钱计划?
- 22.如何用列表记录每一周的存款?
- 23.如何让程序自己数数?—— 用 for 循环解放你的双手
- 24.52周存钱挑战4.0:你的存款计算器能有多灵活?
- 25.52周存钱挑战:怎么根据日期自动查存款?
- 26.Python 怎么判断一年中的第几天?
- 27.列表 vs 元组:哪个更适合存储月份天数?
- 28.用集合给月份分个队,换个思路算天数
- 29.把月份和天数“锁”在一起:用字典给数据配个对
- 30.Python 怎么判断密码强弱?
- 31.Python 怎么给密码设置“防沉迷”系统?
- 32.Python 怎么把密码保存到文件里?
- 33.Python 怎么读取文件里的密码?
- 34.Python 怎么把密码检查工具“打包”起来?
- 35.Python 怎么把文件操作也“打包”起来?
- 36.计算机怎么“扔骰子”?——用Python模拟随机事件
- 37.如何用 Python 模拟掷两个骰子?
- 38.怎么用 Python 把骰子轨迹画出来?
- 39.骰子点数分布长啥样?用直方图一眼看穿!
- 40.用科学计算库让骰子程序“起飞”
- 41.空气质量指数怎么算?手把手教你写一个AQI计算器
- 42.空气质量指数计算:从零开始,让程序看懂空气
- 43.如何读取空气质量数据文件并找出空气质量最好的五个监测点?
- 44.JSON 数据怎么变成 Excel 表格?—— 让数据换个“马甲”
- 45.Python 怎么让程序自己判断文件类型?
- 46.如何让程序自己上网查空气质量?
- 47.用美味的汤来解析网页:Beautiful Soup 入门
- 48.如何让爬虫自动抓取全国所有城市的空气质量?
- 49.爬到的数据怎么存下来?—— 把全国空气质量数据保存为CSV文件
- 50.用 pandas 玩转空气质量数据:找出全国空气最好和最差的城市
- 51.空气质量数据怎么“洗”干净,还能画成图?
骰子点数分布长啥样?用直方图一眼看穿!
约 14 分钟
小象实战讲义 · Python 入门:8 个小项目边玩边学
欢迎回来,骰子模拟师!上一节我们用 matplotlib 画出了骰子点数的散点图,看到了随机性的“散漫”。但这还不够,我们更想知道:投掷一万次,点数7到底出现了多少次?点数2和12是不是真的那么稀有?这一节,我们将用一种更强大的可视化工具——直方图,来直接“看穿”数据的分布规律。学完这一节,你就能一键生成清晰、专业的统计图表,用数据说话!
💡 核心导读
- 直方图是什么:一种展示数据分布情况的“分组统计图”,能直观看出哪个区间数据最多、哪个最少。
plt.hist()的魔力:一行代码,自动完成数据分组、计数和绘图,解放你的双手。- 让图表更专业:调整柱子样式、显示频率、解决中文乱码,让你的图表既好看又好懂。
- 本节唯一新增:引入
plt.hist()函数绘制直方图,并对图表进行基础美化。
直方图:数据分布的“显微镜”
在上一节,我们手动统计了每个点数出现的次数。但如果数据量很大,或者我们想快速了解整体分布,手动统计就太麻烦了。这时候,直方图就是我们的好帮手。
你可以把直方图想象成一个“数据显微镜”。它先把所有可能的数据值(比如我们骰子的点数2到12)分成几个连续的“区间”(也叫“分组”或“桶”),然后数一数落在每个区间里的数据有多少个,最后用柱子的高低把这个数量直观地画出来。
生活中的直方图:人口的身高调查。特别高和特别矮的人都比较少,中等身高的人最多,画出来的直方图就会是中间高、两边低的“小山包”形状(统计学里叫“正态分布”)。我们的两个骰子点数之和,理论上也是中间的点数(如7)出现概率最高,两边的点数(如2和12)概率最低。
用 plt.hist() 一键生成分布图
matplotlib 为我们提供了超级简单的直方图绘制函数 plt.hist()。它的核心参数就两个:
data: 你的数据列表,比如我们记录的所有骰子点数之和。bins: 分组的边界。比如[2, 3, 4, ..., 13]表示分组是[2,3),[3,4), …,[12,13)。
让我们直接升级程序,用直方图来展示结果。为了让代码更专注于核心功能,我们把之前手动统计的部分都去掉,只保留记录每次投掷结果的列表。
import random
import matplotlib.pyplot as plt
random.seed(42) # 固定随机种子,让示例输出可复现
# 解决中文显示问题(稍后解释)
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
def roll_dice():
"""模拟掷一次骰子,返回1到6的随机整数"""
return random.randint(1, 6)
# 主逻辑
total_times = 10000 # 模拟投掷总次数
roll_list = [] # 用于记录每次投掷两个骰子的点数之和
for i in range(total_times):
roll1 = roll_dice()
roll2 = roll_dice()
roll_list.append(roll1 + roll2) # 记录和
# 数据可视化:绘制直方图
# bins=range(2, 14) 创建了 [2,3), [3,4), ..., [12,13) 这些分组
plt.hist(roll_list, bins=range(2, 14))
plt.title('骰子点数统计') # 图表标题
plt.xlabel('点数') # X轴标签
plt.ylabel('出现次数') # Y轴标签
plt.show()运行上面的代码,你会立刻看到一张图表!柱子最高的地方,对应的就是出现次数最多的点数(很可能是7)。看,我们不需要任何额外的统计代码,plt.hist() 帮我们全搞定了!
美化图表:从“能看”到“好看”
生成的图表可能看起来有点“简陋”,柱子之间没有缝隙。我们可以通过 plt.hist() 的更多参数来美化它。
import random
import matplotlib.pyplot as plt
random.seed(42) # 固定随机种子,让示例输出可复现
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
def roll_dice():
return random.randint(1, 6)
total_times = 10000
roll_list = []
for i in range(total_times):
roll_list.append(roll_dice() + roll_dice())
# 绘制美化后的直方图
plt.hist(roll_list,
bins=range(2, 14),
edgecolor='black', # 柱子边缘为黑色
linewidth=1) # 边缘线宽度为1
plt.title('骰子点数统计')
plt.xlabel('点数')
plt.ylabel('出现次数')
plt.show()现在柱子之间有了清晰的黑边,看起来是不是更专业、更易读了?
显示概率:更直观的洞察
“出现1600次”这个数字,不如“概率是16%”来得直观。我们想让Y轴直接显示频率(概率)。plt.hist() 有一个超好用的参数 density,设置 density=True,它就会自动将次数转换为频率密度,使得所有柱子的面积之和为1。
小知识:很早以前的 matplotlib(2.x 时代)这个参数叫
normed,但它在 matplotlib 2.1 被弃用、3.0 起彻底移除,现在统一用density。如果你在很老的教程里看到normed=True,知道它就是今天的density=True即可——现在写normed会直接报错。
import random
import matplotlib.pyplot as plt
random.seed(42) # 固定随机种子,让示例输出可复现
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
def roll_dice():
return random.randint(1, 6)
total_times = 10000
roll_list = []
for i in range(total_times):
roll_list.append(roll_dice() + roll_dice())
# 绘制显示频率的直方图
plt.hist(roll_list,
bins=range(2, 14),
density=True, # 归一化,显示频率
edgecolor='black',
linewidth=1)
plt.title('骰子点数统计')
plt.xlabel('点数')
plt.ylabel('频率')
plt.show()运行后,看看Y轴,是不是变成了0.00, 0.05, 0.10…?最高点对应的频率,就是点数7出现的近似概率。这下,数据分布一目了然!
关于中文显示的小窍门
你可能注意到了代码开头的两行“魔法”:
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False这是因为 matplotlib 默认的字体不支持中文,直接使用中文会显示成小方框 □□□。
- 第一行:将字体设置为支持中文的“黑体”(SimHei)。
- 第二行:解决负号(-)可能显示异常的问题。
记住它:以后只要在用 matplotlib 画图并且要用到中文,把这两行代码放在 import matplotlib.pyplot as plt 之后,其他画图代码之前,就万事大吉了。
📝 动手练一练
改变实验规模:将模拟投掷次数
total_times分别改为 100、1000、100000 次,运行程序观察直方图的变化。随着次数增加,图形的形状有什么趋势?它是否越来越接近一个稳定的、对称的“小山包”形状?模拟三个骰子:如果一次投掷三个骰子,点数之和的范围是3到18。请你修改程序,模拟投掷三个骰子10000次,并用直方图展示结果。猜一猜,哪个点数出现的概率会最高?
👉 点击查看第2题参考答案
思路:需要模拟三个骰子,所以循环内要生成三个随机数并求和。直方图的分组边界 bins 也要相应调整为从3到19(range(3, 20))。
import random
import matplotlib.pyplot as plt
random.seed(42) # 固定随机种子,让示例输出可复现
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
def roll_dice():
return random.randint(1, 6)
total_times = 10000
roll_list_three = [] # 记录三个骰子的和
for i in range(total_times):
# 投掷三个骰子并记录和
roll_list_three.append(roll_dice() + roll_dice() + roll_dice())
# 绘制直方图,分组边界为3到19
plt.hist(roll_list_three,
bins=range(3, 20),
density=True,
edgecolor='black',
linewidth=1)
plt.title('三个骰子点数统计')
plt.xlabel('点数')
plt.ylabel('频率')
plt.show()运行后,你会发现图形仍然是对称的,但最高点对应的点数变成了 10或11(因为3到18的中间值是10.5)。这就是概率论的魅力!
本章小结
恭喜!你成功地为骰子模拟项目装上了“数据分析之眼”。通过直方图,我们不再需要费力地数数,就能一眼看清数据的分布规律,甚至能读出精确的概率。plt.hist() 这个工具,在未来的数据分析工作中会经常用到。
📋 行动清单
- 运行本节最终代码,观察骰子点数的频率分布直方图。
- 修改
total_times参数,感受“大数定律”——实验次数越多,结果越接近理论概率。 - 挑战一下“动手练一练”的第2题,看看三个骰子的世界有什么不同。
—— 小象教研组
配套资料 · 直接下载
课件、代码、数据集等配套资料全部免费,点击即可直接下载,无需分享或解锁。
- 下载第8章代码包:模拟掷骰子(含全部版本 5 个 .py)ZIP · 3KB