Matplotlib 3D绘图中使用fill_between填充线条区域报错:TypeError: can only concatenate str (not "int") to str
你遇到的这个错误其实是参数传递顺序搞错了,导致Matplotlib把你传入的数值当成了step参数来处理,才会出现字符串和整数拼接的错误。
错误原因分析
看你的错误栈,问题出在cbook.STEP_LOOKUP_MAP["steps-" + step]这一行——这里的step被意外赋值成了整数0(或者你传入的数组),而它本来应该是字符串类型的参数(比如'pre'/'post'/'mid')。为什么会这样?因为你调用fill_between的时候,传递了多余的位置参数,这些参数被Matplotlib按顺序分配给了后面的关键字参数(比如step)。
比如你的代码:
for n, item in enumerate(v_bins[:-1]): ax2.fill_between(x, item, s, x, item, 0, facecolors=facecolors[n], alpha=.7)
fill_between的位置参数签名是x, y1, y2=0, where=None, interpolate=False, step=None, **kwargs,所以你传入的第四个参数x会被赋值给where,第五个item给interpolate,第六个0就直接给了step参数,这显然不是你想要的。
解决方法
在3D绘图中使用fill_between,你需要通过zdir和zs参数来指定填充所在的3D平面,而不是直接传递多组坐标作为位置参数。针对你的需求(填充每条曲线下方到z=0的区域),正确的写法如下:
情况1:填充曲线到z=0的完整区域
如果是想直接填充每条曲线(对应y=item)下方到z=0的区域,可以这样写:
for n, item in enumerate(v_bins[:-1]): # 在y=item的平面上,填充x对应的z从0到s的区域 ax2.fill_between(x, 0, s, zdir='y', zs=item, facecolor=facecolors[n], alpha=.7)
情况2:和官方示例一样分两部分填充
如果是需要像官方示例那样,填充z从item到s,以及z从0到item的两部分区域,那就分开调用两次fill_between:
for n, item in enumerate(v_bins[:-1]): # 填充z从item到s的部分 ax2.fill_between(x, item, s, zdir='y', zs=item, facecolor=facecolors[n], alpha=.7) # 填充z从0到item的部分 ax2.fill_between(x, 0, item, zdir='y', zs=item, facecolor=facecolors[n], alpha=.7)
这里的zdir='y'表示我们在y轴方向固定一个值,zs=item就是这个固定的y值,这样fill_between就会在y=item的平面上,绘制x-z方向的填充区域,完美契合你的3D绘图需求。
另外你提到官方示例代码也报错,这应该是因为Matplotlib版本更新后,参数校验更严格了,旧的示例写法已经不符合当前版本的参数规则,用上面的写法就能解决问题。
备注:内容来源于stack exchange,提问作者8abu_Frik

