64 votes

définir le rapport hauteur/largeur du tracé 3D matplotlib ?

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

Le réglage du rapport hauteur/largeur fonctionne pour les tracés 2D :

 ax = plt.axes()
ax.plot([0,1],[0,10])
ax.set_aspect('equal','box')

Mais pas pour la 3D :

 ax = plt.axes(projection='3d')
ax.plot([0,1],[0,1],[0,10])
ax.set_aspect('equal','box')

Existe-t-il une syntaxe différente pour le cas 3D, ou n'est-elle pas implémentée ?

38voto

Matt Panzer Points 571

Depuis matplotlib 3.3.0, Axes3D.set_box_aspect semble être l'approche recommandée.

 import numpy as np
import matplotlib.pyplot as plt

xs, ys, zs = ...
ax = plt.axes(projection='3d')

ax.set_box_aspect((np.ptp(xs), np.ptp(ys), np.ptp(zs)))  # aspect ratio is 1:1:1 in data space

ax.plot(xs, ys, zs)

29voto

Ben Points 635

Je n'ai pas essayé toutes ces réponses, mais ce kludge l'a fait pour moi :

 def axisEqual3D(ax):
    extents = np.array([getattr(ax, 'get_{}lim'.format(dim))() for dim in 'xyz'])
    sz = extents[:,1] - extents[:,0]
    centers = np.mean(extents, axis=1)
    maxsize = max(abs(sz))
    r = maxsize/2
    for ctr, dim in zip(centers, 'xyz'):
        getattr(ax, 'set_{}lim'.format(dim))(ctr - r, ctr + r)

20voto

Dan Points 18107

On dirait que cette fonctionnalité a été ajoutée depuis, alors j'ai pensé ajouter une réponse pour les personnes qui passeront par ce fil à l'avenir comme je l'ai fait :

 fig = plt.figure(figsize=plt.figaspect(0.5)*1.5) #Adjusts the aspect ratio and enlarges the figure (text does not enlarge)
ax = fig.gca(projection='3d')

figaspect(0.5) rend la silhouette deux fois plus large que haute. Ensuite, le *1.5 augmente la taille de la figure. Les étiquettes, etc. n'augmenteront pas, c'est donc un moyen de rendre le graphique moins encombré par les étiquettes.

14voto

jens Points 437

Si vous connaissez les limites, par ex. +-3 centré autour de (0,0,0), vous pouvez ajouter des points invisibles comme ceci :

 import numpy as np
import pylab as pl
from mpl_toolkits.mplot3d import Axes3D
fig = pl.figure()
ax = fig.gca(projection='3d')
ax.set_aspect('equal')
MAX = 3
for direction in (-1, 1):
    for point in np.diag(direction * MAX * np.array([1,1,1])):
        ax.plot([point[0]], [point[1]], [point[2]], 'w')

9voto

Crazymoomin Points 265

Si vous connaissez les limites, vous pouvez également définir le rapport hauteur/largeur de cette façon :

 ax.auto_scale_xyz([minbound, maxbound], [minbound, maxbound], [minbound, maxbound])

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X