Python matplotlib 是否具有在轴坐标中绘制对角线的功能?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22104256/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 00:14:13  来源:igfitidea点击:

Does matplotlib have a function for drawing diagonal lines in axis coordinates?

pythonnumpymatplotlib

提问by mwaskom

Matplotlib Axes have the functions axhlineand axvlinefor drawing horizontal or vertical lines at a given y or x coordinate (respectively) independently of the data scale on an Axes.

Matplotlib Axes 具有用于在给定的 y 或 x 坐标(分别)绘制水平或垂直线的功能,axhline而与Axesaxvline上的数据比例无关。

Is there a similar function for plotting a constant diagonal? For example, if I have a scatterplot of variables with a similar domain, it is often useful to know whether they fall above or below the line of y = x:

是否有用于绘制恒定对角线的类似函数?例如,如果我有一个具有相似域的变量散点图,那么了解它们是落在 线的上方还是下方通常很有用y = x

mean, cov = [0, 0], [(1, .6), (.6, 1)]
x, y = np.random.multivariate_normal(mean, cov, 100).T
y += x + 1
f, ax = plt.subplots(figsize=(6, 6))
ax.scatter(x, y, c=".3")
ax.plot([-3, 3], [-3, 3], ls="--", c=".3")
ax.set(xlim=(-3, 3), ylim=(-3, 3))

enter image description here

在此处输入图片说明

This can of course be done programmatically by grabbing the axis limits, (ax.get_xlim(), etc.), but that a) takes a few extra steps and b) is brittle in cases where more data might end up on the plot and shift the limits. (Actually in some cases just adding the constant line itself stretches the axes).

这当然可以通过抓取轴限制以编程方式完成,(ax.get_xlim()等),但是 a) 需要一些额外的步骤,b) 在更多数据可能最终出现在绘图上并移动限制的情况下很脆弱。(实际上在某些情况下,只需添加恒定线本身即可拉伸轴)。

It would be preferable to just do, e.g., ax.axdline(ls="--", c=".3"), but it's not clear if something like this exists in the matplotlib codebase. All you would need to do would be modify the axhlinecode to plot from [0, 1]in axescoordinates for both xand y, I think.

最好只做,例如,,ax.axdline(ls="--", c=".3")但不清楚 matplotlib 代码库中是否存在这样的东西。所有你需要做的是改变axhline从代码到剧情[0, 1]轴线的两个坐标xy,我想。

回答by Ffisegydd

Plotting a diagonal line based from the bottom-left to the top-right of the screen is quite simple, you can simply use ax.plot(ax.get_xlim(), ax.get_ylim(), ls="--", c=".3"). The method ax.get_xlim()will simply return the current values of the x-axis (and similarly for the y-axis).

绘制一条从屏幕左下角到右上角的对角线非常简单,您只需使用ax.plot(ax.get_xlim(), ax.get_ylim(), ls="--", c=".3"). 该方法ax.get_xlim()将简单地返回 x 轴的当前值(对于 y 轴也是如此)。

However, if you want to be able to zoom using your graph then it becomes slightly more tricky, as the diagonal line that you have plotted will not change to match your new xlims and ylims.

但是,如果您希望能够使用图形进行缩放,那么它会变得稍微棘手一些,因为您绘制的对角线不会更改以匹配您的新 xlims 和 ylims。

In this case you can use callbacks to check when the xlims (or ylims) have changed and change the data in your diagonal line accordingly (as shown below). I found the methods for callbacks in this example. Further information can also be found here

在这种情况下,您可以使用回调来检查 xlims(或 ylims)何时发生更改并相应地更改对角线上的数据(如下所示)。我在这个例子中找到了回调方法。还可以在此处找到更多信息

import numpy as np
import matplotlib.pyplot as plt

mean, cov = [0, 0], [(1, .6), (.6, 1)]
x, y = np.random.multivariate_normal(mean, cov, 100).T
y += x + 1

f, ax = plt.subplots(figsize=(6, 6))

ax.scatter(x, y, c=".3")
ax.set(xlim=(-3, 3), ylim=(-3, 3))

# Plot your initial diagonal line based on the starting
# xlims and ylims.
diag_line, = ax.plot(ax.get_xlim(), ax.get_ylim(), ls="--", c=".3")

def on_change(axes):
    # When this function is called it checks the current
    # values of xlim and ylim and modifies diag_line
    # accordingly.
    x_lims = ax.get_xlim()
    y_lims = ax.get_ylim()
    diag_line.set_data(x_lims, y_lims)

# Connect two callbacks to your axis instance.
# These will call the function "on_change" whenever
# xlim or ylim is changed.
ax.callbacks.connect('xlim_changed', on_change)
ax.callbacks.connect('ylim_changed', on_change)

plt.show()

Note that if you don't want the diagonal line to change with zooming then you simply remove everything below diag_line, = ax.plot(...

请注意,如果您不希望对角线随着缩放而改变,那么您只需删除下面的所有内容 diag_line, = ax.plot(...

回答by JaminSore

Drawing a diagonal from the lower left to the upper right corners of your plot would be accomplished by the following

绘制从左下角到右上角的对角线将通过以下方式完成

ax.plot([0, 1], [0, 1], transform=ax.transAxes)

ax.plot([0, 1], [0, 1], transform=ax.transAxes)

Using transform=ax.transAxes, the supplied xand ycoordinates are interpreted as axescoordinates instead of datacoordinates.

使用transform=ax.transAxes,提供的xy坐标被解释为轴坐标而不是数据坐标。

This, as @fqq pointed out, is only the identity line when your xand ylimits are equal. To draw the line y=xsuch that it always extends to the limits of your plot, an approach similar to the one given by @Ffisegydd would work, and can be written as the following function.

正如@fqq 所指出的,这只是当您xy限制相等时的身份线。要绘制线条y=x以使其始终延伸到您的绘图范围,类似于@Ffisegydd 给出的方法将起作用,并且可以编写为以下函数。

def add_identity(axes, *line_args, **line_kwargs):
    identity, = axes.plot([], [], *line_args, **line_kwargs)
    def callback(axes):
        low_x, high_x = axes.get_xlim()
        low_y, high_y = axes.get_ylim()
        low = max(low_x, low_y)
        high = min(high_x, high_y)
        identity.set_data([low, high], [low, high])
    callback(axes)
    axes.callbacks.connect('xlim_changed', callback)
    axes.callbacks.connect('ylim_changed', callback)
    return axes

Example usage:

用法示例:

import numpy as np
import matplotlib.pyplot as plt

mean, cov = [0, 0], [(1, .6), (.6, 1)]
x, y = np.random.multivariate_normal(mean, cov, 100).T
y += x + 1

f, ax = plt.subplots(figsize=(6, 6))
ax.scatter(x, y, c=".3")
add_identity(ax, color='r', ls='--')

plt.show()

回答by volperossa

If the axes are in the range [0,1], it can be resolved in this way:

如果轴在范围内 [0,1],则可以通过以下方式解决:

ident = [0.0, 1.0]
plt.plot(ident,ident)