如何在Matplotlib 3D柱状图中清晰展示小数值
3D柱状图小数值可视化解决方案
你的问题核心是数据量级差异过大(最大值148+,最小值0.02+),导致小数值柱子被大数值挤压得几乎不可见。以下是几种实用的解决方案:
方案1:使用对数刻度(最推荐)
对数刻度可以压缩大数值的视觉占比,同时放大小数值的差异,让所有量级的数据都能清晰展示:
import matplotlib.pyplot as plt import numpy as np np.random.seed(10) #data time = [[148.64793017553907, 47.00162830693381, 1.3599472795213974, 1.0770502873829435, 0.2416407755443028, 0.051920437812805136], [100.7717864097111, 11.489065728868756, 0.5487183400562831, 0.12449462073189865, 0.15135425840105324, 0.030407779557364272], [10.223643741910418, 1.6037633759634835, 0.3846410546983991, 0.09999658720833912, 0.07089985779353546, 0.029794696399143727], [0.9271023046402703, 0.1371803828648158, 0.3223802804946899, 0.09767089911869589, 0.024286287171500026, 0.029627582005092024], [0.11088135128929497, 0.06808395726340152, 0.224113655090332, 0.08966402666909352, 0.022294637135096912, 0.029868837765284897]] colors = ['r', 'g', 'b', 'y','m'] yticks = [1,2,3,4,5] fig = plt.figure() ax = fig.add_subplot(111 ,projection='3d') ax.set_xlabel('X') ax.set_ylabel('Y') ax.set_zlabel('Z') ax.set_yticks(yticks) # 启用对数刻度,设置最小Z值避免log(0)错误 ax.set_zscale('log') ax.set_zlim(bottom=0.01) xs=np.array([1,2,3,4,5,6]) for i in range(5): ax.bar(xs, time[i], zs=i+1, zdir='y', color=colors[i], alpha=0.8) plt.tight_layout() plt.savefig("3d_log.png") plt.show()
方案2:给柱子添加数值标签
直接在每个柱子顶部标注具体数值,不受视觉高度限制,清晰展示所有数据:
import matplotlib.pyplot as plt import numpy as np np.random.seed(10) #data time = [[148.64793017553907, 47.00162830693381, 1.3599472795213974, 1.0770502873829435, 0.2416407755443028, 0.051920437812805136], [100.7717864097111, 11.489065728868756, 0.5487183400562831, 0.12449462073189865, 0.15135425840105324, 0.030407779557364272], [10.223643741910418, 1.6037633759634835, 0.3846410546983991, 0.09999658720833912, 0.07089985779353546, 0.029794696399143727], [0.9271023046402703, 0.1371803828648158, 0.3223802804946899, 0.09767089911869589, 0.024286287171500026, 0.029627582005092024], [0.11088135128929497, 0.06808395726340152, 0.224113655090332, 0.08966402666909352, 0.022294637135096912, 0.029868837765284897]] colors = ['r', 'g', 'b', 'y','m'] yticks = [1,2,3,4,5] fig = plt.figure() ax = fig.add_subplot(111 ,projection='3d') ax.set_xlabel('X') ax.set_ylabel('Y') ax.set_zlabel('Z') ax.set_yticks(yticks) xs=np.array([1,2,3,4,5,6]) for i in range(5): bars = ax.bar(xs, time[i], zs=i+1, zdir='y', color=colors[i], alpha=0.8) # 给每个柱子添加数值标签,保留4位小数 for bar, val in zip(bars, time[i]): x = bar.get_x() + bar.get_width()/2 y = i+1 z = val ax.text(x, y, z, f'{val:.4f}', ha='center', va='bottom') plt.tight_layout() plt.savefig("3d_labels.png") plt.show()
方案3:拆分图表,分尺度展示
将大数值和小数值分组,分别绘制两个3D图,让每组数据都在合适的尺度下展示:
import matplotlib.pyplot as plt import numpy as np np.random.seed(10) #data time = [[148.64793017553907, 47.00162830693381, 1.3599472795213974, 1.0770502873829435, 0.2416407755443028, 0.051920437812805136], [100.7717864097111, 11.489065728868756, 0.5487183400562831, 0.12449462073189865, 0.15135425840105324, 0.030407779557364272], [10.223643741910418, 1.6037633759634835, 0.3846410546983991, 0.09999658720833912, 0.07089985779353546, 0.029794696399143727], [0.9271023046402703, 0.1371803828648158, 0.3223802804946899, 0.09767089911869589, 0.024286287171500026, 0.029627582005092024], [0.11088135128929497, 0.06808395726340152, 0.224113655090332, 0.08966402666909352, 0.022294637135096912, 0.029868837765284897]] colors = ['r', 'g', 'b', 'y','m'] yticks = [1,2,3,4,5] # 绘制大数值组(Y=1、2) fig1 = plt.figure(figsize=(8,6)) ax1 = fig1.add_subplot(111, projection='3d') ax1.set_xlabel('X') ax1.set_ylabel('Y') ax1.set_zlabel('Z') ax1.set_yticks([1,2]) xs=np.array([1,2,3,4,5,6]) for i in range(2): ax1.bar(xs, time[i], zs=i+1, zdir='y', color=colors[i], alpha=0.8) plt.tight_layout() plt.savefig("3d_large.png") # 绘制小数值组(Y=3、4、5) fig2 = plt.figure(figsize=(8,6)) ax2 = fig2.add_subplot(111, projection='3d') ax2.set_xlabel('X') ax2.set_ylabel('Y') ax2.set_zlabel('Z') ax2.set_yticks([3,4,5]) ax2.set_zlim(bottom=0, top=2) # 聚焦小数值范围 for i in range(2,5): ax2.bar(xs, time[i], zs=i+1, zdir='y', color=colors[i], alpha=0.8) plt.tight_layout() plt.savefig("3d_small.png") plt.show()
方案4:调整Z轴范围(仅关注小数值时使用)
如果只需要分析小数值的差异,可以手动设置Z轴上限,截断大数值柱子:
import matplotlib.pyplot as plt import numpy as np np.random.seed(10) #data time = [[148.64793017553907, 47.00162830693381, 1.3599472795213974, 1.0770502873829435, 0.2416407755443028, 0.051920437812805136], [100.7717864097111, 11.489065728868756, 0.5487183400562831, 0.12449462073189865, 0.15135425840105324, 0.030407779557364272], [10.223643741910418, 1.6037633759634835, 0.3846410546983991, 0.09999658720833912, 0.07089985779353546, 0.029794696399143727], [0.9271023046402703, 0.1371803828648158, 0.3223802804946899, 0.09767089911869589, 0.024286287171500026, 0.029627582005092024], [0.11088135128929497, 0.06808395726340152, 0.224113655090332, 0.08966402666909352, 0.022294637135096912, 0.029868837765284897]] colors = ['r', 'g', 'b', 'y','m'] yticks = [1,2,3,4,5] fig = plt.figure() ax = fig.add_subplot(111 ,projection='3d') ax.set_xlabel('X') ax.set_ylabel('Y') ax.set_zlabel('Z') ax.set_yticks(yticks) # 设置Z轴范围,聚焦小数值 ax.set_zlim(bottom=0, top=2) xs=np.array([1,2,3,4,5,6]) for i in range(5): ax.bar(xs, time[i], zs=i+1, zdir='y', color=colors[i], alpha=0.8) plt.tight_layout() plt.savefig("3d_zoom.png") plt.show()
内容的提问来源于stack exchange,提问作者HaYou
相关产品推荐
相关产品推荐

