Python实战:3种方法教你快速生成茎叶图(附完整代码)

发布时间:2026/5/21 15:20:28

Python实战:3种方法教你快速生成茎叶图(附完整代码) Python实战3种方法教你快速生成茎叶图附完整代码茎叶图是数据分析中一种简单却强大的工具它能让你一眼看穿数据的分布规律。想象一下你手上有50个学生的考试成绩想快速了解整体表现——茎叶图就是你的秘密武器。今天我们不谈枯燥的理论直接上手用Python三种方式实现它从最原始的手工打造到Pandas的优雅处理再到Matplotlib的视觉盛宴。1. 为什么选择茎叶图在数据科学领域我们经常需要在保留原始数据细节的同时观察整体分布。直方图会丢失具体数值箱线图过于抽象而茎叶图恰好填补了这个空白。它特别适合处理50-150个数据点的场景比如班级考试成绩分析小规模用户调研数据实验测量的初步结果产品质量抽检记录茎叶图的核心优势保留每个原始数据点不需要复杂的数据清洗即时显示数据集中趋势一眼识别异常值注意当数据量超过200个点时建议改用直方图或核密度图否则茎叶图会变得过于密集。2. 手工打造茎叶图理解底层逻辑我们先从最基础的实现开始这能帮助你真正理解茎叶图的工作原理。假设我们有以下学生成绩数据scores [72, 85, 90, 63, 77, 88, 91, 68, 75, 82, 95, 101, 107, 65, 79, 83, 92, 99, 104, 110]2.1 基础实现代码def basic_stem_plot(data, stem_width10): 手工实现茎叶图的核心逻辑 stems {} for num in data: stem num // stem_width # 获取茎部分 leaf num % stem_width # 获取叶部分 if stem not in stems: stems[stem] [] stems[stem].append(leaf) # 格式化输出 print(茎 | 叶) print(--------) for stem in sorted(stems.keys()): leaves .join(str(l) for l in sorted(stems[stem])) print(f{stem:2d} | {leaves}) basic_stem_plot(scores)2.2 输出结果分析执行后会得到如下输出茎 | 叶 -------- 6 | 3 5 8 7 | 2 5 7 9 8 | 2 3 5 8 9 | 0 1 2 5 9 10 | 1 4 7 11 | 0这个结果告诉我们最低分是63茎6叶3最高分是110茎11叶0多数学生集中在70-99分区间2.3 进阶优化茎分裂技术当某个茎对应的叶过多时比如超过10个可以采用茎分裂技术提高可读性def split_stem_plot(data, stem_width10, split2): 实现茎分裂的增强版茎叶图 stems {} for num in data: stem num // stem_width leaf num % stem_width # 茎分裂逻辑 split_stem f{stem}.{leaf//(stem_width//split)} if split_stem not in stems: stems[split_stem] [] stems[split_stem].append(leaf % (stem_width//split)) print(茎 | 叶) print(--------) for stem in sorted(stems.keys(), keylambda x: float(x)): leaves .join(str(l) for l in sorted(stems[stem])) print(f{stem:4} | {leaves}) split_stem_plot(scores)3. Pandas实现数据分析师的优雅选择对于已经使用Pandas进行数据处理的分析师我们可以用更简洁的方式实现茎叶图。3.1 基础Pandas实现import pandas as pd def pandas_stem_plot(data, stem_width10): 使用Pandas的向量化操作实现茎叶图 df pd.DataFrame({value: data}) df[stem] df[value] // stem_width df[leaf] df[value] % stem_width # 分组聚合 result (df.groupby(stem)[leaf] .apply(lambda x: .join(map(str, sorted(x)))) .reset_index()) # 美化输出 max_stem_len len(str(result[stem].max())) print(茎.ljust(max_stem_len1) | 叶) print(-*(max_stem_len3) -*10) for _, row in result.iterrows(): print(f{int(row[stem]):{max_stem_len}d} | {row[leaf]}) pandas_stem_plot(scores)3.2 Pandas高级技巧多维度分析结合Pandas的强大功能我们可以轻松实现多维度分析def advanced_pandas_stem(data, group_colNone, stem_width10): 支持分组分析的茎叶图 df pd.DataFrame(data) df[stem] df[value] // stem_width df[leaf] df[value] % stem_width if group_col: # 按分组生成茎叶图 for name, group in df.groupby(group_col): print(f\n {name} ) pandas_stem_plot(group[value].tolist(), stem_width) else: pandas_stem_plot(df[value].tolist(), stem_width) # 示例按班级分析成绩 data { value: [72, 85, 90, 63, 77, 88, 91, 68, 75, 82, 95, 101], class: [A]*6 [B]*6 } advanced_pandas_stem(data, group_colclass)4. Matplotlib可视化让茎叶图更生动虽然传统茎叶图是文本形式的但我们可以用Matplotlib创造更直观的视觉呈现。4.1 基础可视化实现import matplotlib.pyplot as plt def plot_stem(data, stem_width10): 使用Matplotlib绘制茎叶图 stems [x//stem_width for x in data] leaves [x%stem_width for x in data] plt.figure(figsize(10, 6)) markerline, stemlines, baseline plt.stem( stems, leaves, linefmtgrey, markerfmtD, basefmt , use_line_collectionTrue) # 美化设置 plt.setp(markerline, markersize8, colorroyalblue) plt.setp(stemlines, linewidth1.5, alpha0.6) plt.xlabel(f茎 (单位{stem_width}), fontsize12) plt.ylabel(叶, fontsize12) plt.title(学生成绩茎叶图, pad20, fontsize14) plt.grid(axisy, alpha0.3) plt.xticks(sorted(set(stems))) # 添加数据标签 for x, y in zip(stems, leaves): plt.text(x, y0.3, str(y), hacenter, vabottom, fontsize9) plt.tight_layout() plt.show() plot_stem(scores)4.2 高级可视化技巧我们可以进一步增强可视化效果def enhanced_stem_plot(data, stem_width10): 增强版可视化茎叶图 stems np.array([x//stem_width for x in data]) leaves np.array([x%stem_width for x in data]) fig, ax plt.subplots(figsize(12, 7)) # 为每个茎创建箱线图 for stem in np.unique(stems): stem_leaves leaves[stems stem] ax.boxplot(stem_leaves, positions[stem], widths0.6, showfliersFalse, patch_artistTrue, boxpropsdict(facecolorlightblue, alpha0.7)) # 绘制茎叶点 ax.scatter(stems, leaves, cred, s50, alpha0.7, edgecolorswhite, linewidths1) # 添加连接线 for x, y in zip(stems, leaves): ax.plot([x, x], [0, y], grey, alpha0.4, linestyle--) ax.set_xlabel(f茎 (单位{stem_width}), fontsize12) ax.set_ylabel(叶, fontsize12) ax.set_title(增强版茎叶图分析, pad20, fontsize14) ax.grid(axisy, alpha0.3) ax.set_xticks(sorted(np.unique(stems))) plt.tight_layout() plt.show() enhanced_stem_plot(scores)5. 实战应用选择最佳方法三种方法各有优劣下面是快速选择指南方法适用场景优点缺点手工实现教学演示、理解原理完全可控深入理解代码量较大Pandas数据分析流程中简洁高效易整合输出为文本形式Matplotlib报告展示、可视化需求直观美观需要额外美化工作性能对比处理1000个数据点import timeit # 测试手工实现 t1 timeit.timeit(basic_stem_plot(data), setupfrom __main__ import basic_stem_plot; import random; data[random.randint(50,150) for _ in range(1000)], number10) # 测试Pandas实现 t2 timeit.timeit(pandas_stem_plot(data), setupfrom __main__ import pandas_stem_plot; import random; data[random.randint(50,150) for _ in range(1000)], number10) # 测试Matplotlib实现 t3 timeit.timeit(plot_stem(data), setupfrom __main__ import plot_stem; import random; data[random.randint(50,150) for _ in range(1000)], number10) print(f手工实现平均耗时: {t1/10:.4f}s) print(fPandas实现平均耗时: {t2/10:.4f}s) print(fMatplotlib实现平均耗时: {t3/10:.4f}s)典型输出结果手工实现平均耗时: 0.0123s Pandas实现平均耗时: 0.0078s Matplotlib实现平均耗时: 0.0456s实用建议教学场景从手工实现开始日常分析使用Pandas版本报告展示选择Matplotlib可视化大数据集考虑抽样或改用其他图表

相关新闻