<p dir="auto">Traceback (most recent call last):<br>
File "/home/hsy/wh/license_plate/datasets/ccpd.py", line 6, in <br>
import pycocotools.coco as coco<br>
File "/home/hsy/.local/lib/python3.6/site-packages/pycocotools-2.0-py3.6-linux-x86_64.egg/pycocotools/coco.py", line 49, in <br>
import matplotlib.pyplot as plt<br>
File "/home/hsy/.local/lib/python3.6/site-packages/matplotlib-3.3.0-py3.6-linux-x86_64.egg/matplotlib/pyplot.py", line 43, in <br>
from matplotlib.figure import Figure, figaspect<br>
File "/home/hsy/.local/lib/python3.6/site-packages/matplotlib-3.3.0-py3.6-linux-x86_64.egg/matplotlib/figure.py", line 18, in <br>
from matplotlib import docstring, projections<br>
File "/home/hsy/.local/lib/python3.6/site-packages/matplotlib-3.3.0-py3.6-linux-x86_64.egg/matplotlib/projections/<strong>init</strong>.py", line 4, in <br>
from mpl_toolkits.mplot3d import Axes3D<br>
File "/home/hsy/anaconda3/envs/tf15_gpu/lib/python3.6/site-packages/mpl_toolkits/mplot3d/<strong>init</strong>.py", line 1, in <br>
from .axes3d import Axes3D<br>
File "/home/hsy/anaconda3/envs/tf15_gpu/lib/python3.6/site-packages/mpl_toolkits/mplot3d/axes3d.py", line 24, in <br>
import matplotlib.projections as proj<br>
<strong>AttributeError: module 'matplotlib' has no attribute 'projections'</strong><br>
What does this question mean？(My matplotlib version is 3.3.0)</p>
<h1 dir="auto">Summary</h1>
<p dir="auto">Currently, when you plot several artists on the same axis and use the pyplot.legend(), the ordering of the entries is somewhat mysterious for the average user, see <a href="http://stackoverflow.com/questions/22263807/how-is-order-of-items-in-matplotlib-legend-determined" rel="nofollow">http://stackoverflow.com/questions/22263807/how-is-order-of-items-in-matplotlib-legend-determined</a>.</p>
<p dir="auto">Like many of my peers, I use matplotlib to make plots for science publications and regularly want to customize the order of the items in the legend when I polish plots. I argue that this is a common thing to do, and therefore it should be easy to do with the API.</p>
<p dir="auto">My request is to add a new keyword <code class="notranslate">lorder</code> to artist constructors, similar to <code class="notranslate">zorder</code>. While <code class="notranslate">zorder</code> handles the drawing order, <code class="notranslate">lorder</code> handles the order in which items appear in the legend.</p>
<h1 dir="auto">Current state</h1>
<p dir="auto">tacaswell explained on SO that the order of legend items is an implementation detail and that's fine. There are ways to re-order the items, but they are somewhat cumbersome. One recommended way is to use</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="[...]
handles, labels = axis.get_legend_handles_labels()"><pre class="notranslate">[...]
<span class="pl-s1">handles</span>, <span class="pl-s1">labels</span> <span class="pl-c1">=</span> <span class="pl-s1">axis</span>.<span class="pl-en">get_legend_handles_labels</span>()</pre></div>
<p dir="auto">and then reorder to your hearts desire. This is ok when you want to reorder based on a rule, but it is not convenient when you want to re-order manually (because you first have to find out what the current order is, unpack the tuples, reorder them, repack them).</p>
<p dir="auto">The other recommended way is to keep the return values of pyplot</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="[...]
art1, = pyplot.plot(...)
art2, = pyplot.plot(...)
# I always forget how to do it for errorbar
# art3, = pyplot.errorbar(...) # fails, unpacking works differently here
plt.legend((art1, art2), (&quot;label1&quot;, &quot;label2&quot;))"><pre class="notranslate">[...]
<span class="pl-s1">art1</span>, <span class="pl-c1">=</span> <span class="pl-s1">pyplot</span>.<span class="pl-en">plot</span>(...)
<span class="pl-s1">art2</span>, <span class="pl-c1">=</span> <span class="pl-s1">pyplot</span>.<span class="pl-en">plot</span>(...)
<span class="pl-c"># I always forget how to do it for errorbar</span>
<span class="pl-c"># art3, = pyplot.errorbar(...) # fails, unpacking works differently here</span>
<span class="pl-s1">plt</span>.<span class="pl-en">legend</span>((<span class="pl-s1">art1</span>, <span class="pl-s1">art2</span>), (<span class="pl-s">"label1"</span>, <span class="pl-s">"label2"</span>))</pre></div>
<p dir="auto">As you can see, I always have trouble remembering how to unpack the return value correctly for stuff other than pyplot.plot(...) so that it works with plt.legend(...). Surely, other users must feel the same way. I would say that this method relies on knowing more about the matplotlib internals than the average user wants to know.</p>
<h1 dir="auto">Proposed solution</h1>
<p dir="auto">The user simply specifies the new <code class="notranslate">lorder</code> keyword in calls to pyplot</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="[...]
pyplot.plot(..., lorder=2, label=&quot;second&quot;) # appears second in legend
pyplot.plot(..., lorder=3, label=&quot;third&quot;) # appears third in legend
pyplot.errorbar(..., lorder=1, label=&quot;first&quot;) # appears first in legend
plt.legend()"><pre class="notranslate">[...]
<span class="pl-s1">pyplot</span>.<span class="pl-en">plot</span>(..., <span class="pl-s1">lorder</span><span class="pl-c1">=</span><span class="pl-c1">2</span>, <span class="pl-s1">label</span><span class="pl-c1">=</span><span class="pl-s">"second"</span>) <span class="pl-c"># appears second in legend</span>
<span class="pl-s1">pyplot</span>.<span class="pl-en">plot</span>(..., <span class="pl-s1">lorder</span><span class="pl-c1">=</span><span class="pl-c1">3</span>, <span class="pl-s1">label</span><span class="pl-c1">=</span><span class="pl-s">"third"</span>) <span class="pl-c"># appears third in legend</span>
<span class="pl-s1">pyplot</span>.<span class="pl-en">errorbar</span>(..., <span class="pl-s1">lorder</span><span class="pl-c1">=</span><span class="pl-c1">1</span>, <span class="pl-s1">label</span><span class="pl-c1">=</span><span class="pl-s">"first"</span>) <span class="pl-c"># appears first in legend</span>
<span class="pl-s1">plt</span>.<span class="pl-en">legend</span>()</pre></div>
<p dir="auto">This code is rather clear and makes it very easy to specify the ordering of items in the legend. As far as I understand tacaswell, it should be easy to handle internally as well, just make <code class="notranslate">lorder</code> part of the internal sorting criterion.</p>
<p dir="auto">A more explicit alternative is keyword <code class="notranslate">labelorder</code> instead of the shorter <code class="notranslate">lorder</code>.</p>