如何绘制二维NumPy数组列表的Matplotlib概率质量函数(PMF)?
正确绘制已计算好的PMF的方法
你遇到的问题很典型:plt.hist()是用来生成直方图的,它会自动对数据进行区间分组并计算频数/频率,而你已经手动计算出了每个离散取值对应的精确概率(也就是PMF),所以直接用直方图肯定和你的预期结果不符。
针对你已经得到的二维NumPy数组格式的PMF(第一列是离散取值,第二列是对应概率),应该用**条形图(bar)或者阶梯图(step)**来绘制,这两种方式更适合展示离散概率分布。
方法一:单场景PMF绘制
如果只需要绘制单个场景的PMF,代码可以这么写:
import matplotlib.pyplot as plt import numpy as np # 用你给出的示例PMF数组来测试 sample_pmf = np.array([ [0.00000000e+00, 1.91734780e-01], [1.00000000e+00, 2.94277080e-02], [2.00000000e+00, 3.28276369e-01], [3.00000000e+00, 4.43357154e-01], [4.00000000e+00, 3.54294582e-03], [5.00000000e+00, 1.57306794e-03], [6.00000000e+00, 2.00530733e-03], [7.00000000e+00, 2.95245485e-05], [8.00000000e+00, 2.24386568e-05], [9.00000000e+00, 2.83435665e-05], [1.00000000e+01, 1.18098194e-06], [1.20000000e+01, 1.18098194e-06] ]) # 提取取值和概率列 vals = sample_pmf[:, 0] probs = sample_pmf[:, 1] # 绘制条形图 plt.figure(figsize=(10, 6)) plt.bar(vals, probs, width=0.8, align='center', color='#1f77b4', alpha=0.7) # 添加标签和标题 plt.xlabel('离散取值') plt.ylabel('概率') plt.title('单个场景的概率质量函数(PMF)') plt.xticks(vals) # 强制显示所有离散取值作为x轴刻度 plt.grid(axis='y', linestyle='--', alpha=0.7) plt.show()
方法二:多场景PMF对比绘制
如果你有多个场景的PMF需要对比,可以给每个场景的条形设置偏移,避免重叠:
import matplotlib.pyplot as plt import numpy as np # 假设plot_pmf是你存储所有场景PMF的列表 plot_pmf = [sample_pmf, sample_pmf * 0.9 + 0.01] # 模拟第二个场景的PMF plt.figure(figsize=(12, 6)) bar_width = 0.35 # 每个条形的宽度 for idx, pmf_arr in enumerate(plot_pmf): vals = pmf_arr[:, 0] probs = pmf_arr[:, 1] # 给每个场景的x轴位置加偏移,避免条形重叠 plt.bar(vals + idx * bar_width, probs, width=bar_width, align='center', alpha=0.7, label=f'场景{idx+1}') plt.xlabel('离散取值') plt.ylabel('概率') plt.title('多场景PMF对比') plt.legend() plt.xticks(vals + bar_width/2, vals) # 调整x轴刻度位置 plt.grid(axis='y', linestyle='--', alpha=0.7) plt.show()
为什么之前的直方图结果不对?
你用plt.hist(bl[0])得到的是原始模拟数据的直方图,它会:
- 自动将数据划分成连续区间(bins)
- 计算每个区间内的数据频数,再转换成频率
这和你手动计算的PMF完全不同——你的PMF是每个精确离散值对应的概率,尤其是那些小概率的大取值(比如10、12),直方图会把它们合并到同一个区间里,导致展示的结果和你计算的PMF差异极大。
额外小技巧:阶梯图展示PMF
如果想要更简洁的离散分布展示,也可以用阶梯图:
plt.step(vals, probs, where='mid', linewidth=2, label='PMF') plt.scatter(vals, probs, color='red') # 加上每个点的标记 plt.legend() plt.show()
内容的提问来源于stack exchange,提问作者user7886633
相关产品推荐
相关产品推荐

