drawing a 45 degrees reference line as well as making x and y axis equal range

I am trying to make the following scatterplot:

enter image description here

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'

enter image description here

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')

enter image description here


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: enter image description here


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:

Example output