制作双色3D柱状图遇TypeError报错,求排查思路
3D双色柱状图代码报错分析与解决
问题场景
尝试制作沿纵轴分双色的3D柱状图,编写Python代码如下:
import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D # 创建示例数据 x = np.array([1, 2, 3]) y = np.array([4, 5, 6]) z1 = np.array([1, 2, 3]) z2 = np.array([4, 5, 6]) z3 = np.array([7, 8, 9]) color1 = np.array(['r', 'g', 'b']) color2 = np.array(['y', 'm', 'c']) # 创建画布和3D轴 fig = plt.figure() ax = fig.add_subplot(111, projection='3d') # 绘制第一组柱子 for i in range(len(x)): ax.bar(x[i], z1[i], y[i], zdir='y', color=color1[i], alpha=0.8) ax.bar(x[i], z1[i] - z1[i], y[i], zdir='y', color=color2[i], alpha=0.8) # 绘制第二组柱子 for i in range(len(x)): ax.bar(x[i], z2[i], y[i]+0.5, zdir='y', color=color1[i], alpha=0.8) ax.bar(x[i], z2[i] - z2[i], y[i]+0.5, zdir='y', color=color2[i], alpha=0.8) # 绘制第三组柱子 for i in range(len(x)): ax.bar(x[i], z3[i], y[i]+1.0, zdir='y', color=color1[i], alpha=0.8) ax.bar(x[i], z3[i] - z3[i], y[i]+1.0, zdir='y', color=color2[i], alpha=0.8) # 设置轴标签和标题 ax.set_xlabel('X axis') ax.set_ylabel('Y axis') ax.set_zlabel('Z axis') ax.set_title('3D Bar Chart') # 显示图像 plt.show()
在Windows 11系统的VSCode(Python 3.10)中运行时,出现如下报错:
Traceback (most recent call last): File "c:\Users\16168\Documents\delta-scan-master\delta-scan-master\test\eval_test_display.py", line 73, in ax.bar(x[i], z1[i], y[i], zdir='y', color=color1[i], alpha=0.8) File "C:\Users\16168\Documents\delta-scan-master\delta-scan-master\env\lib\site-packages\matplotlib\__init__.py", line 1459, in inner return func(ax, *map(sanitize_sequence, args), **kwargs) File "C:\Users\16168\Documents\delta-scan-master\delta-scan-master\env\lib\site-packages\mpl_toolkits\mplot3d\axes3d.py", line 2318, in bar zs = np.broadcast_to(zs, len(left)) TypeError: object of type 'numpy.int32' has no len()
报错原因解析
- 报错行指向逻辑:报错回溯指向第73行的
ax.bar调用,是因为错误是在调用该函数后,由matplotlib内部代码触发的。内部代码中的len(left)里的left是你传入的x[i]——单个numpy.int32标量,对单个整数调用len()自然会报错,而非你的代码里直接写了len()导致的问题。 - 参数类型要求:
mpl_toolkits.mplot3d.Axes3D.bar函数期望接收**序列类型(数组/列表)**作为位置参数,而非单个标量。当你传入单个标量时,函数内部无法对其执行len()操作,从而抛出类型错误。该问题和i的类型、len(x)的返回值无关。
解决思路与修正代码
方案1:将单个标量转为单元素数组
在循环中把每个传入的标量参数用np.array()包裹,转为单元素数组,满足函数对参数类型的要求:
import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D # 创建示例数据 x = np.array([1, 2, 3]) y = np.array([4, 5, 6]) z1 = np.array([1, 2, 3]) z2 = np.array([4, 5, 6]) z3 = np.array([7, 8, 9]) color1 = np.array(['r', 'g', 'b']) color2 = np.array(['y', 'm', 'c']) # 创建画布和3D轴 fig = plt.figure() ax = fig.add_subplot(111, projection='3d') # 绘制第一组柱子 for i in range(len(x)): ax.bar(np.array([x[i]]), z1[i], np.array([y[i]]), zdir='y', color=color1[i], alpha=0.8) ax.bar(np.array([x[i]]), 0, np.array([y[i]]), zdir='y', color=color2[i], alpha=0.8) # 绘制第二组柱子 for i in range(len(x)): ax.bar(np.array([x[i]]), z2[i], np.array([y[i]+0.5]), zdir='y', color=color1[i], alpha=0.8) ax.bar(np.array([x[i]]), 0, np.array([y[i]+0.5]), zdir='y', color=color2[i], alpha=0.8) # 绘制第三组柱子 for i in range(len(x)): ax.bar(np.array([x[i]]), z3[i], np.array([y[i]+1.0]), zdir='y', color=color1[i], alpha=0.8) ax.bar(np.array([x[i]]), 0, np.array([y[i]+1.0]), zdir='y', color=color2[i], alpha=0.8) # 设置轴标签和标题 ax.set_xlabel('X axis') ax.set_ylabel('Y axis') ax.set_zlabel('Z axis') ax.set_title('3D Bar Chart') # 显示图像 plt.show()
方案2:批量传入数组,避免循环(更高效)
直接利用numpy数组的广播特性,一次性传入整组数据,无需循环,同时修正原代码中高度为0的无效柱子逻辑:
import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D # 创建示例数据 x = np.array([1, 2, 3]) y = np.array([4, 5, 6]) z1 = np.array([1, 2, 3]) z2 = np.array([4, 5, 6]) z3 = np.array([7, 8, 9]) color1 = np.array(['r', 'g', 'b']) color2 = np.array(['y', 'm', 'c']) # 定义柱子下半段高度(可根据需求调整) z_base = np.array([0.5, 1, 1.5]) # 创建画布和3D轴 fig = plt.figure() ax = fig.add_subplot(111, projection='3d') # 第一组双色柱子:下半段+上半段 ax.bar(x, z_base, y, zdir='y', color=color2, alpha=0.8) ax.bar(x, z1 - z_base, y, zdir='y', bottom=z_base, color=color1, alpha=0.8) # 第二组双色柱子 ax.bar(x, z_base, y+0.5, zdir='y', color=color2, alpha=0.8) ax.bar(x, z2 - z_base, y+0.5, zdir='y', bottom=z_base, color=color1, alpha=0.8) # 第三组双色柱子 ax.bar(x, z_base, y+1.0, zdir='y', color=color2, alpha=0.8) ax.bar(x, z3 - z_base, y+1.0, zdir='y', bottom=z_base, color=color1, alpha=0.8) # 设置轴标签和标题 ax.set_xlabel('X axis') ax.set_ylabel('Y axis') ax.set_zlabel('Z axis') ax.set_title('3D Bar Chart') # 显示图像 plt.show()
内容的提问来源于stack exchange,提问作者Koerner Gray Buchta
相关产品推荐
相关产品推荐

