2013-05-10 11 views
8

Ho trascorso gli ultimi giorni a cercare un modo per rimuovere i piccoli margini dagli assi in una trama 3D. Ho provato ax.margins(0) e ax.autoscale_view('tight') e altri approcci, ma questi piccoli margini sono ancora lì. In particolare, non mi piace che gli istogrammi delle barre siano elevati, vale a dire che il loro fondo non è al livello zero - vedi l'immagine di esempio.Rimozione dei margini degli assi nella trama 3D

unwanted margins on all axes

In gnuplot, userei "xyplane impostato a 0". In matplotlib, poiché ci sono margini su ogni asse su entrambi i lati, sarebbe bello poter controllare ognuno di essi.

Edit: soluzione di HYRY seguito funziona bene, ma l'asse 'X' ottiene una linea di griglia disegnata su di esso a Y = 0:

strange axis

+0

Sarebbe di grande aiuto se si potrebbe aggiungere il codice usi per fare la trama, quindi abbiamo un punto di partenza. Quindi è più facile per le persone copiare e incollare il codice e successivamente trovare una soluzione per questo particolare problema. – hooy

+0

Un sacco di codice di esempio [qui] (http://matplotlib.org/mpl_toolkits/mplot3d/tutorial.html) (l'esempio "Bar diagrammi" è simile al mio caso sopra). – dolphin

risposta

6

Non è proprietà o metodo che può modificare questi margini. Devi patchare il codice sorgente. Ecco un esempio:

from mpl_toolkits.mplot3d import Axes3D 
import matplotlib.pyplot as plt 
import numpy as np 
###patch start### 
from mpl_toolkits.mplot3d.axis3d import Axis 
if not hasattr(Axis, "_get_coord_info_old"): 
    def _get_coord_info_new(self, renderer): 
     mins, maxs, centers, deltas, tc, highs = self._get_coord_info_old(renderer) 
     mins += deltas/4 
     maxs -= deltas/4 
     return mins, maxs, centers, deltas, tc, highs 
    Axis._get_coord_info_old = Axis._get_coord_info 
    Axis._get_coord_info = _get_coord_info_new 
###patch end### 

fig = plt.figure() 
ax = fig.add_subplot(111, projection='3d') 
for c, z in zip(['r', 'g', 'b', 'y'], [30, 20, 10, 0]): 
    xs = np.arange(20) 
    ys = np.random.rand(20) 

    # You can provide either a single color or an array. To demonstrate this, 
    # the first bar of each set will be colored cyan. 
    cs = [c] * len(xs) 
    cs[0] = 'c' 
    ax.bar(xs, ys, zs=z, zdir='y', color=cs, alpha=0.8) 

ax.set_xlabel('X') 
ax.set_ylabel('Y') 
ax.set_zlabel('Z') 

plt.show() 

Il risultato è:

enter image description here

Modifica

Per cambiare il colore delle linee della griglia:

for axis in (ax.xaxis, ax.yaxis, ax.zaxis): 
    axis._axinfo['grid']['color'] = 0.7, 1.0, 0.7, 1.0 

Edi t2

Set X & Y lim:

ax.set_ylim3d(-1, 31) 
ax.set_xlim3d(-1, 21) 
+0

Grazie, ha funzionato ... (1) se cambio 'per c, z in zip (['r', 'g', 'b', 'y'], [30, 20, 10, 2]), perché l'asse "X" assume uno spesso stile tratteggiato? (2) Come cambiare i colori delle linee della griglia? 'ax.grid (color = 'blue')' non funziona. – dolphin

+0

@dolphin, puoi pubblicare il risultato di (1)? Per (2), il colore non può essere modificato da qualche API, ho aggiunto il codice che ha cambiato il dettato _axinfo nascosto. – HYRY

+0

Grazie per (2)! È un peccato che la complessità e la flessibilità di matplotlib si traducano in così tanti "hack" che devono essere cercati individualmente, e talvolta le soluzioni intuitive funzionano, a volte no.Riguardo a (1), non ho potuto pubblicare un'immagine in un commento, quindi ho incollato un pezzo di codice sperando che tu possa riprodurlo :-) Ora ho aggiunto un'altra immagine come Modifica nella domanda originale. – dolphin

0

ho dovuto modificare leggermente la soluzione accettata, perché nel mio caso le assi x ed y (ma non la z) ha un margine supplementare che, stampando mins, maxs, deltas, risulta essere deltas * 6.0/11. Ecco la patch aggiornata che ha funzionato bene nel mio caso.

###patch start### 
from mpl_toolkits.mplot3d.axis3d import Axis 
def _get_coord_info_new(self, renderer): 
    mins, maxs, cs, deltas, tc, highs = self._get_coord_info_old(renderer) 
    correction = deltas * [1.0/4 + 6.0/11, 
          1.0/4 + 6.0/11, 
          1.0/4] 
    mins += correction 
    maxs -= correction 
    return mins, maxs, cs, deltas, tc, highs 
if not hasattr(Axis, "_get_coord_info_old"): 
    Axis._get_coord_info_old = Axis._get_coord_info 
Axis._get_coord_info = _get_coord_info_new 
###patch end### 

(ho anche cambiato la logica di patching un po 'intorno, in modo che la modifica della funzione e ricaricando il suo modulo ora funziona come previsto in Jupyter.)

Problemi correlati