enter image description here

上图是由以下代码生成的

%matplotlib
import numpy as np
import matplotlib.pyplot as plt
x = y = np.array([1, 2])

fig = plt.figure(figsize=(5, 3))
ax1 = fig.add_subplot(111, projection='3d')
ax1.bar3d(x, y, [0,0], 0.5, 0.5, [1,1], shade=True, label='a')
ax1.bar3d(x, y, [1,1], 0.5, 0.5, [1,1], shade=True, label='b')
ax1.legend()

这也需要一个传奇.如你所见,没有传奇,但我有这个回溯

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Cell In[1], line 12
     10 ax1.bar3d(x, y, [0,0], 0.5, 0.5, [1,1], shade=True, label='a')
     11 ax1.bar3d(x, y, [1,1], 0.5, 0.5, [1,1], shade=True, label='b')
---> 12 plt.legend()

File /usr/lib64/python3.11/site-packages/matplotlib/pyplot.py:2646, in legend(*args, **kwargs)
   2644 @_copy_docstring_and_deprecators(Axes.legend)
   2645 def legend(*args, **kwargs):
-> 2646     return gca().legend(*args, **kwargs)

File /usr/lib64/python3.11/site-packages/matplotlib/axes/_axes.py:313, in Axes.legend(self, *args, **kwargs)
    311 if len(extra_args):
    312     raise TypeError('legend only accepts two non-keyword arguments')
--> 313 self.legend_ = mlegend.Legend(self, handles, labels, **kwargs)
    314 self.legend_._remove_method = self._remove_legend
    315 return self.legend_

File /usr/lib64/python3.11/site-packages/matplotlib/_api/deprecation.py:454, in make_keyword_only.<locals>.wrapper(*args, **kwargs)
    448 if len(args) > name_idx:
    449     warn_deprecated(
    450         since, message="Passing the %(name)s %(obj_type)s "
    451         "positionally is deprecated since Matplotlib %(since)s; the "
    452         "parameter will become keyword-only %(removal)s.",
    453         name=name, obj_type=f"parameter of {func.__name__}()")
--> 454 return func(*args, **kwargs)

File /usr/lib64/python3.11/site-packages/matplotlib/legend.py:517, in Legend.__init__(self, parent, handles, labels, loc, numpoints, markerscale, markerfirst, scatterpoints, scatteryoffsets, prop, fontsize, labelcolor, borderpad, labelspacing, handlelength, handleheight, handletextpad, borderaxespad, columnspacing, ncols, mode, fancybox, shadow, title, title_fontsize, framealpha, edgecolor, facecolor, bbox_to_anchor, bbox_transform, frameon, handler_map, title_fontproperties, alignment, ncol)
    514 self._alignment = alignment
    516 # init with null renderer
--> 517 self._init_legend_box(handles, labels, markerfirst)
    519 tmp = self._loc_used_default
    520 self._set_loc(loc)

File /usr/lib64/python3.11/site-packages/matplotlib/legend.py:782, in Legend._init_legend_box(self, handles, labels, markerfirst)
    779         text_list.append(textbox._text)
    780         # Create the artist for the legend which represents the
    781         # original artist/handle.
--> 782         handle_list.append(handler.legend_artist(self, orig_handle,
    783                                                  fontsize, handlebox))
    784         handles_and_labels.append((handlebox, textbox))
    786 columnbox = []

File /usr/lib64/python3.11/site-packages/matplotlib/legend_handler.py:119, in HandlerBase.legend_artist(self, legend, orig_handle, fontsize, handlebox)
     95 """
     96 Return the artist that this HandlerBase generates for the given
     97 original artist/handle.
   (...)
    112 
    113 """
    114 xdescent, ydescent, width, height = self.adjust_drawing_area(
    115          legend, orig_handle,
    116          handlebox.xdescent, handlebox.ydescent,
    117          handlebox.width, handlebox.height,
    118          fontsize)
--> 119 artists = self.create_artists(legend, orig_handle,
    120                               xdescent, ydescent, width, height,
    121                               fontsize, handlebox.get_transform())
    123 if isinstance(artists, _Line2DHandleList):
    124     artists = [artists[0]]

File /usr/lib64/python3.11/site-packages/matplotlib/legend_handler.py:806, in HandlerPolyCollection.create_artists(self, legend, orig_handle, xdescent, ydescent, width, height, fontsize, trans)
    802 def create_artists(self, legend, orig_handle,
    803                    xdescent, ydescent, width, height, fontsize, trans):
    804     p = Rectangle(xy=(-xdescent, -ydescent),
    805                   width=width, height=height)
--> 806     self.update_prop(p, orig_handle, legend)
    807     p.set_transform(trans)
    808     return [p]

File /usr/lib64/python3.11/site-packages/matplotlib/legend_handler.py:78, in HandlerBase.update_prop(self, legend_handle, orig_handle, legend)
     76 def update_prop(self, legend_handle, orig_handle, legend):
---> 78     self._update_prop(legend_handle, orig_handle)
     80     legend._set_artist_props(legend_handle)
     81     legend_handle.set_clip_box(None)

File /usr/lib64/python3.11/site-packages/matplotlib/legend_handler.py:787, in HandlerPolyCollection._update_prop(self, legend_handle, orig_handle)
    783         return None
    785 # orig_handle is a PolyCollection and legend_handle is a Patch.
    786 # Directly set Patch color attributes (must be RGBA tuples).
--> 787 legend_handle._facecolor = first_color(orig_handle.get_facecolor())
    788 legend_handle._edgecolor = first_color(orig_handle.get_edgecolor())
    789 legend_handle._original_facecolor = orig_handle._original_facecolor

File /usr/lib64/python3.11/site-packages/matplotlib/legend_handler.py:775, in HandlerPolyCollection._update_prop.<locals>.first_color(colors)
    774 def first_color(colors):
--> 775     if colors.size == 0:
    776         return (0, 0, 0, 0)
    777     return tuple(colors[0])

AttributeError: 'tuple' object has no attribute 'size'

你能帮我理解一下发生了什么吗?

推荐答案

  • 给出了操作中的代码
  • The Traceback mentions several relevant lines in legend_handler.py
    • anaconda3\lib\site-packages\matplotlib\legend_handler.py,第89行
      • 如果orig_handlePoly3DCollection,则发生self._update_prop.
        • 对于2D堆叠条形图,未调用此方法.
    • anaconda3\lib\site-packages\matplotlib\legend_handler.py,795线路呼叫def first_color
  • 一百零二

colors from bar3d

  • colorsnp.arraystuple,没有.size的方法.
legend_handle → Rectangle(xy=(-0, -0), width=20, height=7, angle=0)
orig_handle → <mpl_toolkits.mplot3d.art3d.Poly3DCollection object at 0x00000253CF287AD0>

# colors tuple of arrays, which causes AttributeError: 'tuple' object has no attribute 'size'
colors =\
(np.array([0.05065359, 0.19444443, 0.29411763, 1.]), np.array([0.06483662, 0.24888894, 0.37647067, 1.]), np.array([0.10738562, 0.41222224, 0.62352943, 1.]), np.array([0.05065359, 0.19444443, 0.29411763, 1.]), np.array([0.05065359, 0.19444443, 0.29411763, 1.]), np.array([0.0932026 , 0.35777772, 0.54117639, 1.]), np.array([0.06483662, 0.24888894, 0.37647067, 1.]), np.array([0.10738562, 0.41222224, 0.62352943, 1.]), np.array([0.10738562, 0.41222224, 0.62352943, 1.]), np.array([0.05065359, 0.19444443, 0.29411763, 1.]), np.array([0.0932026 , 0.35777772, 0.54117639, 1.]), np.array([0.10738562, 0.41222224, 0.62352943, 1.]))

line 781 of legend_handler.py

  • colors = np.array(colors)可以创建图例,但我不知道会出现什么问题.
class HandlerPolyCollection(HandlerBase):

    def _update_prop(self, legend_handle, orig_handle):
        def first_color(colors):
            print(colors)  # added to check 
            colors = np.array(colors)  # added to fix
            if colors.size == 0:
                return (0, 0, 0, 0)
            return tuple(colors[0])

enter image description here


How to create a legend for 3D bar似乎是一个更安全的 Select .

x = y = np.array([1, 2])

fig = plt.figure(figsize=(5, 3))
ax1 = fig.add_subplot(111, projection='3d')
ax1.bar3d(x, y, [0,0], 0.5, 0.5, [1,1], shade=True, label='a', color='tab:blue')
blue_proxy = plt.Rectangle((0, 0), 1, 1, fc="tab:blue")

ax1.bar3d(x, y, [1,1], 0.5, 0.5, [1,1], shade=True, label='b', color='tab:orange')
orange_proxy = plt.Rectangle((0, 0), 1, 1, fc="tab:orange")

ax1.legend([blue_proxy, orange_proxy], ['a', 'b'], bbox_to_anchor=(1.1, 0.5), loc='center left', frameon=False)

enter image description here

Python相关问答推荐

Pandas .类型错误:只能将字符串(而不是int)连接到字符串

无法获得指数曲线_fit来处理日期

Pandas数据帧处理Pandas表中Json内的嵌套列表以获取后续Numpy数组

如何使用函数正确索引收件箱?

使用Curses for Python保存和恢复终端窗口内容

使用Beautiful Soup获取第二个srcset属性

如何修复使用turtle和tkinter制作的绘画应用程序的撤销功能

使用Ubuntu、Python和Weasyprint的Docker文件-venv的问题

Pythind 11无法弄清楚如何访问tuple元素

根据条件将新值添加到下面的行或下面新创建的行中

如何使用pandasDataFrames和scipy高度优化相关性计算

根据在同一数据框中的查找向数据框添加值

为什么我的Python代码在if-else声明中的行之前执行if-else声明中的行?

重新匹配{ }中包含的文本,其中文本可能包含{{var}

运行Python脚本时,用作命令行参数的SON文本

删除所有列值,但判断是否存在任何二元组

更改键盘按钮进入'

为一个组的每个子组绘制,

使用特定值作为引用替换数据框行上的值

如何使用使用来自其他列的值的公式更新一个rabrame列?