matplotlib 图例中的两个相邻符号

2024-01-04

我想在图例中的同一行上识别两个不同的符号(具有不同的颜色)。下面,我尝试使用代理艺术家执行此操作,但结果是它们在图例中彼此堆叠。我希望它们彼此相邻或一个在另一个之上——这样它们都是可见的。

from pylab import *
import matplotlib.lines as mlines

#define two colors, one for 'r' data, one for 'a' data
rcolor=[69./255 , 115./255, 50.8/255 ]
acolor=[202./255, 115./255, 50.8/255 ]

#Plot theory:
ax2.plot(rho, g_r, '-',color=rcolor,lw=2) 
ax2.plot(rho, g_a, '-',color=acolor,lw=2)  
#Plot experiment:
ax2.scatter(X_r, Y_r,s=200, marker='s', facecolors='none', edgecolors=rcolor); 
ax2.scatter(X_a, Y_a,s=200, marker='^', facecolors='none', edgecolors=acolor); 

#Create Proxy Artists for legend
expt_r = mlines.Line2D([], [], fillstyle='none', color=rcolor, marker='s', linestyle='', markersize=15)
expt_a = mlines.Line2D([], [], fillstyle='none', color=acolor, marker='^', linestyle='', markersize=15)
thry_r = mlines.Line2D([], [], fillstyle='none', color=rcolor, marker='', markersize=15)
thry_a = mlines.Line2D([], [], fillstyle='none', color=acolor, marker='', markersize=15)

#Add legend
ax2.legend(((expt_r,expt_a),(thry_r,thry_a)), ('Experiment','Theory'))

我认为我的问题几乎与此一模一样:(Matplotlib,一个标签具有多个不同标记的图例 https://stackoverflow.com/questions/9262307/matplotlib-legend-with-multiple-different-markers-with-one-label),但问题似乎尚未解决,因为那里的答案只是将一个补丁绘制在另一个补丁之上,这也正是我所发生的情况。我觉得也许我需要以某种方式制作一个复合补丁,但我很难找到如何做到这一点。谢谢!

另外,我还没有找到如何使图例符号看起来与散点符号相同(线条粗细、大小)。再次感谢。


重叠补丁(又名艺术家)的问题在于您在创建图例时如何定义手柄和标签。引用matplotlib图例指南 https://matplotlib.org/tutorials/intermediate/legend_guide.html:

默认的 handler_map 有一个特殊的元组处理程序(legend_handler.HandlerTuple),它简单地为给定元组中的每一项绘制句柄。

让我们首先检查一下您作为示例给出的图例的结构。任何可迭代对象都可以用于句柄和标签,因此我选择将它们存储为列表,与图例指南中给出的一些示例一致并使代码更清晰:

ax2.legend([(expt_r, expt_a), (thry_r, thry_a)], ['Experiment', 'Theory'])

handles_list = [(expt_r, expt_a), (thry_r, thry_a)]
handles1 = (expt_r, expt_a) # tuple of 2 handles (aka legend keys) representing the markers
handles2 = (thry_r, thry_a) # same, these represent the lines

labels_list = ['Experiment', 'Theory']
label1 = 'Experiment'
label2 = 'Theory'

无论包含多少个句柄handles1 or in handles2,它们都会被相应的绘制在彼此之上label1 and label2,因为它们包含在单个元组中。要解决此问题并单独绘制键/符号,您必须将它们从元组中取出,如下所示:

handles_list = [expt_r, expt_a, thry_r, thry_a]

但现在你面临的问题是,只有expt_r, expt_a由于标签列表仅包含两个标签,因此将绘制句柄。然而这里的目标是避免不必要地重复这些标签。以下是如何解决此问题的示例。它是基于您提供的代码示例构建的,并利用图例参数 https://matplotlib.org/api/_as_gen/matplotlib.pyplot.legend.html:

import numpy as np                 # v 1.19.2
import matplotlib.pyplot as plt    # v 3.3.2

# Set data parameters
rng = np.random.default_rng(seed=1)
data_points = 10
error_scale = 0.2

# Create variables
rho = np.arange(0, data_points)
g_r = rho**2
g_r_error = rng.uniform(-error_scale, error_scale, size=g_r.size)*g_r
g_a = rho**2 + 50
g_a_error = rng.uniform(-error_scale, error_scale, size=g_a.size)*g_a

X_r = rho
Y_r = g_r + g_r_error
X_a = rho
Y_a = g_a + g_a_error

# Define two colors, one for 'r' data, one for 'a' data
rcolor = [69./255 , 115./255, 50.8/255 ]
acolor = [202./255, 115./255, 50.8/255 ]
# Create figure with single axes
fig, ax = plt.subplots(figsize=(9,5))

# Plot theory: notice the comma after each variable to unpack the list
# containing one Line2D object returned by the plotting function
# (because it is possible to plot several lines in one function call)
thry_r, = ax.plot(rho, g_r, '-', color=rcolor, lw=2)
thry_a, = ax.plot(rho, g_a, '-', color=acolor, lw=2)

# Plot experiment: no need for a comma as the PathCollection object
# returned by the plotting function is not contained in a list
expt_r = ax.scatter(X_r, Y_r, s=100, marker='s', facecolors='none', edgecolors=rcolor) 
expt_a = ax.scatter(X_a, Y_a, s=100, marker='^', facecolors='none', edgecolors=acolor)

# Create custom legend: input handles and labels in desired order and
# set ncol=2 to line up the legend keys of the same type.
# Note that seeing as the labels are added here with explicitly defined
# handles, it is not necessary to define the labels in the plotting functions.
ax.legend(handles=[thry_r, expt_r, thry_a, expt_a],
          labels=['', '', 'Theory','Experiment'],
          loc='upper left', ncol=2, handlelength=3, edgecolor='black',
          borderpad=0.7, handletextpad=1.5, columnspacing=0)

plt.show()

问题已解决,但可以简化代码以自动创建图例。通过使用以下命令,可以避免将每个绘图函数的输出存储为新变量:get_legend_handles_labels https://matplotlib.org/api/_as_gen/matplotlib.axes.Axes.get_legend_handles_labels.html功能。这是基于相同数据构建的示例。请注意,添加了第三种类型的图(误差带),以使句柄和标签的处理更加清晰:

# Define parameters used to process handles and labels
nb_plot_types = 3   # theory, experiment, error band
nb_experiments = 2  # r and a

# Create figure with single axes
fig, ax = plt.subplots(figsize=(9,5))

# Note that contrary to the previous example, here it is necessary to 
# define a label in the plotting functions seeing as the returned
# handles/artists are this time not stored as variables. No labels means
# no handles in the handles list returned by the 
# ax.get_legend_handles_labels() function.

# Plot theory
ax.plot(rho, g_r, '-', color=rcolor, lw=2, label='Theory')
ax.plot(rho, g_a, '-', color=acolor, lw=2, label='Theory')

# Plot experiment
ax.scatter(X_r, Y_r, s=100, marker='s', facecolors='none',
           edgecolors=rcolor, label='Experiment') 
ax.scatter(X_a, Y_a, s=100, marker='^', facecolors='none',
           edgecolors=acolor, label='Experiment')

# Plot error band
g_r_lower = g_r - error_scale*g_r
g_r_upper = g_r + error_scale*g_r
ax.fill_between(X_r, g_r_lower, g_r_upper,
                color=rcolor, alpha=0.2, label='Uncertainty')
g_a_lower = g_a - error_scale*g_a
g_a_upper = g_a + error_scale*g_a
ax.fill_between(X_a, g_a_lower, g_a_upper,
                color=acolor, alpha=0.2, label='Uncertainty')
# Extract handles and labels and reorder/process them for the custom legend,
# based on the number of types of plots and the number of experiments.
# The handles list returned by ax.get_legend_handles_labels() appears to be 
# always ordered the same way with lines placed first, followed by collection 
# objects in  alphabetical order, regardless of the order of the plotting
# functions calls. So if you want to display the legend keys in a different 
# order (e.g. put lines on the bottom line) you will have to process the
# handles list in another way.
handles, labels = ax.get_legend_handles_labels()
handles_ordered_arr = np.array(handles).reshape(nb_plot_types, nb_experiments).T
handles_ordered = handles_ordered_arr.flatten()
# Note the use of asterisks to unpack the lists of strings
labels_trimmed = *nb_plot_types*[''], *labels[::nb_experiments]

# Create custom legend with the same format as in the previous example
ax.legend(handles_ordered, labels_trimmed,
          loc='upper left', ncol=nb_experiments, handlelength=3, edgecolor='black',
          borderpad=0.7, handletextpad=1.5, columnspacing=0)

plt.show()

附加文档:传奇级 https://matplotlib.org/api/legend_api.html, 艺术家班 https://matplotlib.org/api/artist_api.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

matplotlib 图例中的两个相邻符号 的相关文章

随机推荐

  • 无法从 Windows 主机连接到 WSL2 上的本地服务器

    我有一个Python项目使用waitress在 WSL2 Ubuntu 20 上的本地主机上提供服务 我从 VSCode 远程启动服务器 但无法使用地址从 Windows 上的浏览 器连接到它http 127 0 0 1 5998 http
  • Objective-C:如何替换 HTML 实体? [复制]

    这个问题在这里已经有答案了 我从互联网获取文本 它包含 html 实体 即 oacute 我想将此文本显示到自定义 iPhone 单元格中 我尝试在自定义单元格中使用 UIWebView 但我更喜欢使用多行 UILabel 问题是我找不到任
  • 如何让 favicon.ico 在龙卷风上工作

    龙卷风服务器默认不执行 favicon ico 所以我总是得到这样的信息 W 130626 10 38 16 web 1514 404 GET favicon ico 192 168 1 57 0 57ms 我以各种方式使用 web sta
  • 是否有用于 Java 或 PHP 的 OData 服务器库来公开 OData?

    我想知道是否有或为什么没有适用于 Java 的 ADO NET 数据服务服务器库 我需要从 Java 服务器公开数据库 但我只看到 Microsoft 为 java 提供客户端 而不是服务器部分 当您需要 NET Windows 来公开它时
  • CSS :before 和 :first-child 组合

    我使用以下代码在菜单项之间添加分隔符 navigation center li before content color fff 现在我希望第一个项目前面没有分隔符 所以我想出了以下代码 navigation center li befor
  • 在 Python 中递归地重新加载包(及其子模块)

    在 Python 中 您可以按如下方式重新加载模块 import foobar import importlib importlib reload foobar 这适用于 py文件 但对于 Python 包 它只会重新加载包并not任何嵌套
  • Angular HttpClient:“Blob”类型上不存在属性“headers”[重复]

    这个问题在这里已经有答案了 我正在使用 Angular 5 这是我从服务器下载文件的代码 1 服务 export url return this http get url responseType blob 2 组件代码 public do
  • ios6如何播放视频

    我很困惑 MPMoviePlayerViewController 和 MPMoviePlayerController 在 ios6 中本地播放视频的最佳方式是什么 这是我的代码 NSURL url NSURL fileURLWithPath
  • 导航回屏幕时不会调用 useEffect - React Navigation

    我有一个屏幕 可以调用 api 来获取一些数据 然后显示 我看到的一个问题是 当我离开屏幕 我使用的是 React navigation 6 x 然后返回到屏幕时useEffect 没有被调用 从我到目前为止读到的内容来看 这取决于user
  • 如何从进程名获取进程id?

    我正在尝试创建一个 shell 脚本来获取进程号我的 Mac 上的 Skype 应用程序 ps clx grep Skype grep Skype awk print 2 头 1 上面的方法工作正常 但是有两个问题 1 The grep如果
  • 如何获取其他应用的日志?

    我想从其他应用程序读取日志并过滤它们 以便当记录某个关键字时 我的应用程序将执行特定任务 我找到了几种读取日志的方法 但从我的测试来看 我只能获取我的应用程序日志 这是我最初尝试使用的方法 try Process process Runti
  • 如何知道 postNotificationName:object:userInfo 崩溃的位置

    有什么方法可以知道 Xcode 4 6 中的崩溃原因吗 The crash stack is Exception Type SIGSEGV Exception Codes SEGV ACCERR at 0xd9f2c061 Crashed
  • 使用 WebSockets...高效吗?

    我几乎阅读了所有关于 WebSockets 的指南和教程 但没有一个涵盖如何有效地使用它们 有人有关于如何执行此操作的任何指南吗 我担心单个连接可以占用的带宽量 特别是当应用程序打开数百个连接时 WebSocket 的效率取决于处理它们的
  • 使用 BookSleeve 的 ConnectionUtils.Connect() 将 SignalR 与 Redis 消息总线故障转移结合使用

    我正在尝试使用 SignalR 应用程序创建 Redis 消息总线故障转移场景 首先 我们尝试了一个简单的硬件负载平衡器故障转移 它只是监控两个 Redis 服务器 SignalR 应用程序指向单个 HLB 端点 然后 我使一台服务器出现故
  • 为什么选择排序不贪心

    我发现选择排序使用暴力策略 不过 我认为它使用了贪婪策略 为什么我认为它使用贪婪 它在外循环中从 0 到 n 1 从 i 1 到 n 1 这实在是太天真了 它在每次迭代中选择最小元素 它选择本地最好的元素 一切都像 贪婪 中的那样 但事实并
  • Python-将字符串中的单词与字符串列表进行匹配

    我是 python 新手 我想知道字符串比较是如何完成的 假设我有一个包含州名称的字符串列表 例如 states New York California Nebraska Idaho 我还有另一个包含地址的字符串 例如 postal add
  • 从 Django 模型获取数据并使用 AJAX 在 html 表中显示

    我已经搜索并实现了很多不同的方法来显示 html 表 使用 AJAX 从 JsonResponse Django 但无济于事 目前 我得到的最远的是对网络控制台的响应 products model products product pk 2
  • 多列上的 SELECT COUNT(DISTINCT...) 错误?

    我有一个表 VehicleModelYear 其中包含列 id 年份 品牌和型号 以下两个查询按预期工作 SELECT DISTINCT make model FROM VehicleModelYear SELECT COUNT DISTI
  • JS Regex - 替换 Markdown 链接的内容

    我几乎已经解决了一个正则表达式问题 只是一件小事 我正在尝试得到这个 and so use chalk api red string options 进入这个 and so use chalk red string options 我有这个
  • matplotlib 图例中的两个相邻符号

    我想在图例中的同一行上识别两个不同的符号 具有不同的颜色 下面 我尝试使用代理艺术家执行此操作 但结果是它们在图例中彼此堆叠 我希望它们彼此相邻或一个在另一个之上 这样它们都是可见的 from pylab import import mat