drawing a 45 degrees reference line as well as making x and y axis equal range
I am trying to make the following scatterplot:
To something that has X and Y axis equal range as well as overlaying a 45 degree reference line on the scatterplot. I have this code but produces a plot that is not my expectation. How can I fix it?
fig = plt.figure()
ax = fig.add_subplot(111)
#ax.set_aspect('equal', adjustable='box')
plt.scatter(actuals.cpu(), predictions.cpu(), cmap='viridis')
plt.xlabel('Ground Truth')
plt.ylabel('Predictions')
plt.axis('equal')
xpoints = ypoints = plt.xlim()
plt.plot(xpoints, ypoints, linestyle='--', color='k', lw=3, scalex=False, scaley=False)
plt.savefig('predictions_actuals_scatterplot.png')
Here are my Python and matplotlib versions:
$ python
Python 3.8.10 (default, Nov 26 2021, 20:14:08)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import matplotlib
>>> matplotlib.__version__
'3.5.1'
If I just use the following code, while the origin is met by the 45 degree line, still is not exactly what I am looking for.
fig = plt.figure()
ax = fig.add_subplot(111)
plt.scatter(actuals.cpu(), predictions.cpu(), cmap='viridis')
plt.xlabel('Ground Truth')
plt.ylabel('Predictions')
xpoints = ypoints = plt.xlim()
plt.plot(xpoints, ypoints, linestyle='--', color='k', lw=3, scalex=False, scaley=False)
plt.savefig('predictions_actuals_scatterplot.png')
Is this what you are wanting?
import numpy as np
import matplotlib.pyplot as plt
# Generate random data.
x = np.random.random(120) * 0.21 + 0.24
y = np.random.random(120) * 1.4 - 0.2
ticks = np.arange( -0.2, 1.2, step=0.2 )
plt.scatter(x, y, cmap='viridis')
plt.xticks( ticks )
plt.yticks( ticks )
plt.plot( [-.2,1.2], [-.2,1.2], linestyle='--', color='k' )
plt.show()
Output:
The problem is that the plt.axis('equal') request is applied when the figure is rendered, which is after you call plt.xlim(). The solution I suggest is below, which uses both plt.xlim() as well as plt.ylim(). In this way, you do not have to know about the input data ranges in advance.
import matplotlib.pyplot as plt
import numpy as np
rng = np.array([0.2, 1.5])
offset = np.array([0.25, -0.2])
xy = np.random.rand(30, 2) * rng + offset
plt.scatter(xy[:, 0], xy[:, 1], label="points")
plt.axis("equal")
left, right = plt.xlim()
bottom, top = plt.ylim()
axlim = (min(bottom, left), max(top, right))
# you can see the problem here: you've requested
# axes equal, but that has not yet been applied
# to the axes.
print(f"bottom={bottom}, top={top}, left={left}, right={right}")
print(f"Axis limits: {axlim}")
# better solution
xpoints2 = ypoints2 = np.linspace(axlim[0], axlim[1])
plt.plot(xpoints2, ypoints2, color="m", label="xlim and ylim")
# equivalent to the non-working solution
xpoints = ypoints = np.linspace(left, right)
plt.plot(xpoints, ypoints, color="g", label="xlim")
print(f"{left} {right}")
plt.grid()
plt.legend()
plt.show()
Example output: