Matplotlib Axes have the functions axhline
and axvline
for drawing horizontal or vertical lines at a given y or x coordinate (respectively) independently of the data scale on an Axes.
Matplotlib轴具有axhline和axvline函数,用于在给定的y或x坐标(分别)上绘制水平或垂直线,与Axes上的数据比例无关。
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))
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 axhline
code to plot from [0, 1]
in axes coordinates for both x
and y
, I think.
最好只做例如ax.axdline(ls =“ - ”,c =“。3”),但不清楚matplotlib代码库中是否存在这样的东西。我想你需要做的就是修改axhline代码以在x和y的轴坐标中从[0,1]绘图。
2 个解决方案
#1
27
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(...下面的所有内容)。
#2
21
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 x
and y
coordinates are interpreted as axes coordinates instead of data coordinates.
使用transform = ax.transAxes,提供的x和y坐标被解释为轴坐标而不是数据坐标。
This, as @fqq pointed out, is only the identity line when your x
and y
limits are equal. To draw the line y=x
such 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指出的那样,当你的x和y限制相等时,这只是身份线。要绘制线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()
#1
27
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(...下面的所有内容)。
#2
21
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 x
and y
coordinates are interpreted as axes coordinates instead of data coordinates.
使用transform = ax.transAxes,提供的x和y坐标被解释为轴坐标而不是数据坐标。
This, as @fqq pointed out, is only the identity line when your x
and y
limits are equal. To draw the line y=x
such 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指出的那样,当你的x和y限制相等时,这只是身份线。要绘制线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()