告别沉闷的直方图:绘制高颜值的威尔金森图与麦穗图 [复制链接]
发表于 2026-2-5 14:11:35 | 显示全部楼层 |阅读模式
在数据可视化天下中,我们常常用直方图来形貌数据的分布环境,但本日我想先容两种特殊而优雅的点状图变体:威尔金森点状图麦穗图
它们像数据天下的"点彩派"画家,用简朴的点创造出丰富的信息条理。
直方图相比,这种点绘法不但可以或许更直观地展示数据分布的细节,还能更好地显现数据之间的关系和模式,使得观察者可以或许从更广阔的视角明白数据集的特点。
1. 威尔金森点状图

想象一下,你有一袋彩色弹珠,须要按颜色分类展示。如果只是简朴地把全部弹珠倒出来,它们会七零八落。
但如果你为每种颜色准备一个小盒子,把类似颜色的弹珠整齐地堆叠在内里,这就是威尔金森点状图根本头脑
威尔金森点状图将数据点堆叠在对应的数值地区,形成类似直方图的分布展示,但保存了每个数据点的个体性。
它不是用条形的高度体现频率,而是用实际的数据点数目来可视化分布。
下面基于matplotlib库封装了一个绘制威尔金森点状图的函数。
  1. def wilkinson_dot_plot(
  2.     data, bins=10, dot_size=40, dot_spacing=0.8, show_stats=True, random_seed=42
  3. ):
  4.     """
  5.     创建威尔金森点状图
  6.     参数:
  7.     data: 输入数据(一维数组)
  8.     bins: 分组数量或分组边界
  9.     dot_size: 点的大小
  10.     dot_spacing: 点之间的垂直间距
  11.     random_seed: 随机种子
  12.     """
  13.     np.random.seed(random_seed)
  14.     # 创建图形
  15.     fig, ax = plt.subplots(figsize=(10, 7))
  16.     # 计算直方图数据
  17.     hist, bin_edges = np.histogram(data, bins=bins)
  18.     # 为每个分组创建点
  19.     max_count = 0  # 记录最大堆叠高度
  20.     bin_centers = []  # 保存每个分组的中心位置
  21.     # 省略...
  22.     plt.tight_layout()
  23.     return fig, ax, (bin_edges, hist)
复制代码
威尔金森点状图的核默算法可以分解为几个步调:

  • 数据分箱:将连续数据分成多少个等宽的区间
  • 点位置盘算:在每个区间内,将数据点垂直堆叠
  • 克制重叠:通过调解点的垂直位置防止重叠,同时保持可读性
使用起来也简朴:
  1. # 生成示例数据
  2. np.random.seed(42)
  3. # 数据集:正态分布
  4. data_normal = np.random.normal(100, 15, 100)
  5. dot_size = 200
  6. # 创建威尔金森点状图
  7. fig1, ax1, stats1 = wilkinson_dot_plot(data_normal, bins=12, dot_size=dot_size)
  8. plt.show()
复制代码

2. 麦穗图

如果把威尔金森点状图比作整齐堆叠的弹珠,那么麦穗图就像是旷野中的麦穗——每个数据点都像一颗麦粒,正确地生长在本身的位置上,展示实在际数值。
麦穗图威尔金森点状图的一种变体,它将点放置在实在际数值位置,而不是分组中央。
这保存了数据的正确性,同时通过堆叠克制了重叠。
麦穗图的实现与威尔金森点状图类似,但有一个关键区别:点沿x轴放置在实际数据值位置,而不是分组中央。
  1. # 封装麦穗图函数
  2. def strip_plot(
  3.     data,
  4.     bin_edges=None,
  5.     bins=10,
  6.     dot_size=40,
  7.     dot_spacing=0.8,
  8.     jitter_amount=0.2,
  9.     random_seed=42,
  10. ):
  11.     """
  12.     创建麦穗图(在威尔金森点状图基础上显示实际值)
  13.     参数:
  14.     data: 输入数据(一维数组)
  15.     bin_edges: 可选,使用预定义的分组边界
  16.     bins: 如果未提供bin_edges,则使用此参数创建分组
  17.     dot_size: 点的大小
  18.     dot_spacing: 点之间的垂直间距
  19.     jitter_amount: 水平抖动程度(避免重叠)
  20.     random_seed: 随机种子
  21.     """
  22.     np.random.seed(random_seed)
  23.     # 创建图形
  24.     fig, ax = plt.subplots(figsize=(10, 7))
  25.     # 如果没有提供分组边界,则计算
  26.     if bin_edges is None:
  27.         hist, bin_edges = np.histogram(data, bins=bins)
  28.     else:
  29.         hist, bin_edges = np.histogram(data, bins=bin_edges)
  30.     # 对数据进行排序
  31.     sorted_data = np.sort(data)
  32.     # 将数据分配到对应的分组
  33.     data_by_bin = []
  34.     for i in range(len(bin_edges) - 1):
  35.         lower, upper = bin_edges[i], bin_edges[i + 1]
  36.         bin_data = sorted_data[(sorted_data >= lower) & (sorted_data < upper)]
  37.         data_by_bin.append(bin_data)
  38.     # 处理最后一个分组(包含最大值)
  39.     if len(data) > 0:
  40.         last_bin_data = sorted_data[sorted_data >= bin_edges[-2]]
  41.         if len(data_by_bin) > 0:
  42.             data_by_bin[-1] = last_bin_data
  43.     # 绘制麦穗图
  44.     max_points_in_bin = 0
  45.    
  46.     # 省略 ...
  47.     plt.tight_layout()
  48.     return fig, ax, (bin_edges, data_by_bin)
复制代码
使用起来也简朴:
  1. # 生成示例数据
  2. np.random.seed(42)
  3. # 数据集:正态分布
  4. data_normal = np.random.normal(100, 15, 100)
  5. dot_size = 200
  6. # 创建的麦穗图
  7. bin_edges = 12
  8. fig2, ax2, stats2 = strip_plot(
  9.     data_normal, bin_edges=bin_edges, dot_size=dot_size, jitter_amount=0.15
  10. )
  11. plt.show()
复制代码

3. 两种图的应用场景

下面模仿一个门生考试结果分布的分析场景,看看上面两种点状图的应用。
  1. # 示例:学生考试成绩分布分析
  2. print("示例:学生考试成绩分布分析")
  3. print("-" * 40)
  4. # 创建模拟的考试成绩数据
  5. np.random.seed(42)
  6. exam_scores = np.concatenate(
  7.     [
  8.         np.random.normal(65, 8, 45),  # 中等水平学生
  9.         np.random.normal(85, 6, 30),  # 优秀学生
  10.         np.random.normal(45, 10, 24),  # 需要帮助的学生
  11.     ]
  12. )
  13. # 过滤掉不合理分数
  14. exam_scores = np.clip(exam_scores, 0, 100)
  15. print(f"学生总数: {len(exam_scores)}")
  16. print(f"分数范围: {exam_scores.min():.1f} - {exam_scores.max():.1f}")
  17. print(f"平均分: {exam_scores.mean():.1f}")
  18. print(f"及格率: {(exam_scores >= 60).sum() / len(exam_scores) * 100:.1f}%\n")
  19. # 使用威尔金森点状图
  20. print("创建威尔金森点状图...")
  21. fig1, ax1, stats1 = wilkinson_dot_plot(
  22.     exam_scores,
  23.     bins=[0, 40, 60, 70, 80, 90, 100],
  24. )
  25. plt.show()
  26. # 使用麦穗图
  27. print("创建麦穗图...")
  28. fig2, ax2, stats2 = strip_plot(
  29.     exam_scores,
  30.     bins=[0, 40, 60, 70, 80, 90, 100],
  31.     jitter_amount=0.15,
  32. )
  33. plt.show()
  34. ## 输出结果:
  35. '''
  36. 示例:学生考试成绩分布分析
  37. ----------------------------------------
  38. 学生总数: 99
  39. 分数范围: 25.1 - 94.4
  40. 平均分: 65.3
  41. 及格率: 63.6%
  42. '''
复制代码


在门生考试结果分析这个场景中:

  • 威尔金森点状图:将分数分构成区间(如60-70分),全部该区间的门生点都堆叠在区间中央,清楚地展示了分数段的团体分布形态,类似直方图但能看到个体点。
  • 麦穗图:点在实际分数位置堆叠(如65分、68分等),既表现了每个门生的具体分数,又通过垂直堆叠克制了重叠,保存了数据的正确性。
总的来说,威尔金森点状图看分布形态(区间视角),麦穗图看具体数值(正确视角)。
4. 总结

威尔金森点状图麦穗图为数据可视化工具箱增长了优雅而实用的工具。
它们补充了传统直方图散点图之间的空缺,提供了同时展示数据分布和个体数据点的独特方式。
在数据可视化中,选择符合的图表范例就像选择正确的工具来完成工作。
威尔金森点状图麦穗图提供了独特的视角,让我们可以或许同时看到丛林和树木——既明白团体分布,又关注个体数据点。
完备代码分享:威尔金森与麦穗图.ipynb (访问暗码: 6872)

免责声明:如果侵犯了您的权益,请联系站长及时删除侵权内容,谢谢合作!qidao123.com:ToB企服之家,中国第一个企服评测及软件市场,开放入驻,技术点评得现金.

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表