1

I'm trying to do some simple 3D plots but the scatter points appear not to align properly with the axes. This graph should have points aligned with x=1, y=1, z=1. This issue also occurs using the tkinter backend.

MATPLOTLIB 3D scatter

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

x = np.array([-1, -0.5, 0, 0.5, 1]) 
y = np.array([-1, -0.5, 0, 0.5, 1]) 
z = np.array([-1, -0.5, 0, 0.5, 1]) 

fig = plt.figure()
ax = fig.add_subplot(projection='3d')

xyz = np.meshgrid(x,y,z)
ax.scatter(xyz[0], xyz[1], xyz[2], marker='.')

plt.show()

The following links seem loosely related, but I'm unable to put together a concrete solution.

https://github.com/matplotlib/matplotlib/issues/11836

https://github.com/matplotlib/matplotlib/issues/1077/

Python 3.11.1, Matplotlib 3.7.1, Windows 10

craigB
  • 372
  • 1
  • 3
  • 13

3 Answers3

4

As pointed by @jared in comment, points are aligned as expected. You can see it by rotating the graph. Here is another view, using a copy paste of the code you provided, after rotating the figure to face one of the axis: rotated graph .

matleg
  • 618
  • 4
  • 11
  • Thanks! So there is no way for it to look correct with the default perspective? This angle is less useful for my application. – craigB Jun 28 '23 at 08:40
  • You're welcome. I haven't tried this one but I would suggest something like this to start with: https://stackoverflow.com/a/12905458/13339621 . – matleg Jun 28 '23 at 09:28
0

What you are seeing is not a misalignment, but a consequence of viewing 3D information in 2D form, i.e. this is caused by the projection. In general, I do not recommend showing static 3D scatterplots; either share them as interactive media or create animations of the figure rotating (such as in this link shared by @matleg).

Note: There are other projection options in Matplotlib, as documented here, but they do not fix this issue. Orthogonal is essentially using parallel lines of vision while the default (perspective) is more realistic to how we actually see things. The figure below shows how your example looks different when using those two projection options.

import numpy as np
import matplotlib.pyplot as plt

plt.close("all")

x = np.array([-1, -0.5, 0, 0.5, 1]) 
y = np.array([-1, -0.5, 0, 0.5, 1]) 
z = np.array([-1, -0.5, 0, 0.5, 1]) 
X, Y, Z = np.meshgrid(x,y,z)

fig, (ax1, ax2) = plt.subplots(1, 2, subplot_kw={"projection":"3d"})
ax1.scatter(X, Y, Z, marker='.')
ax1.view_init(elev=0, azim=0, roll=0)
ax1.set_title("Default")
ax2.scatter(X, Y, Z, marker='.')
ax2.view_init(elev=0, azim=0, roll=0)
ax2.set_proj_type("ortho")
ax2.set_title("Orthogonal")
fig.show()

jared
  • 4,165
  • 1
  • 8
  • 31
0

It is possible to remove the small offsets at the start of each axis which may improve the appearance of the alignment.

See Correctly setting the axes limits in 3d plots

craigB
  • 372
  • 1
  • 3
  • 13