195

I wish to draw lines on a square graph.

The scales of x-axis and y-axis should be the same.

e.g. x ranges from 0 to 10 and it is 10cm on the screen. y has to also range from 0 to 10 and has to be also 10 cm.

The square shape has to be maintained, even if I mess around with the window size.

Currently, my graph scales together with the window size.

How may I achieve this?

UPDATE:

I tried the following, but it did not work.

plt.xlim(-3, 3)
plt.ylim(-3, 3)
plt.axis('equal')
Trenton McKinney
  • 43,885
  • 25
  • 111
  • 113
Sibbs Gambling
  • 18,128
  • 38
  • 90
  • 168
  • It is working for me. Can you post an entire code example which does not work? And can you explain what is not working? Do you want only the samen scale? Or also the same range? – joris Aug 01 '13 at 12:53
  • 1
    @joris basically I want a fixed SQUARE graph. Even if I maximize the window, I hope that the SQUARE is reserved. My screen is wide, after I maximize the window, the graph becomes also rectangular. I want it to be still SQUARE – Sibbs Gambling Aug 01 '13 at 13:01
  • Again, can you post a full code example. Because the given answer should do that, preserve it as a square. Not preserve its width or heigth, but preserve its shape. – joris Aug 01 '13 at 13:09
  • 2
    Please try to be a bit less abrasive when interacting with others on SO. You are getting help out of people's kindness so act a little less entitled. – tacaswell Aug 01 '13 at 13:57
  • for 3d, you have to do a little bit extra work: http://stackoverflow.com/questions/13685386/matplotlib-equal-unit-length-with-equal-aspect-ratio-z-axis-is-not-equal-to – Trevor Boyd Smith Oct 21 '16 at 16:07

5 Answers5

262

You need to dig a bit deeper into the api to do this:

from matplotlib import pyplot as plt
plt.plot(range(5))
plt.xlim(-3, 3)
plt.ylim(-3, 3)
plt.gca().set_aspect('equal', adjustable='box')
plt.draw()

doc for set_aspect

Cris Luengo
  • 49,445
  • 7
  • 57
  • 113
tacaswell
  • 79,602
  • 19
  • 200
  • 189
  • 4
    Awesome! It indeed works like charm. Could you please tell me what `plt.plot(range(5))` and `plt.gca().set_aspect('equal', adjustable='box')` do, if you don't mind? Also, I notice that even if I don't have `plt.draw()`, the plot will still show up. Then what is the use of it? – Sibbs Gambling Aug 02 '13 at 01:43
  • the `plot` is just have something to show. For the `set_aspect` read the documentation link. The `draw` is just to make sure it gets rendered. – tacaswell Aug 02 '13 at 01:49
  • Sorry but I am asking about the range(5) thing inside plot(). What does the range(5) do? – Sibbs Gambling Aug 02 '13 at 02:00
  • ah, `range(5)` returns `[0, 1, 2, 3, 4]` See: http://docs.python.org/2/library/functions.html#range – tacaswell Aug 02 '13 at 02:03
  • yah, I know it returns that, but then why do I feed the list to plot()? – Sibbs Gambling Aug 02 '13 at 02:06
  • 1
    to have some fake data to plot (it should have plotted a straight line). – tacaswell Aug 02 '13 at 02:08
  • 1
    @perfectionm1ng no worries, took me a while to figure out what you were asking. – tacaswell Aug 02 '13 at 02:40
  • I don't see the need to set both limits to the same ranges, this can result in different scales, especially when most plots are not square shaped. – Mehdi Apr 11 '17 at 12:23
  • 1
    Is there a way to get this done without having to specify exactly the limits? I would have expected there to be a simple command to get a square plot with the same scale and ticks for both axis. Thanks – Confounded Feb 25 '20 at 10:34
  • @Confounded: As stated below, if you don't want to give any limits you can just use `plt.axis('square')` – Isi Aug 03 '20 at 14:55
  • This is really great, thank you. For a specific subplot you can also do `ax.set_aspect('equal', adjustable='box')` – ofekp Nov 08 '21 at 21:09
93
plt.axis('scaled')

works well for me.

Georgy
  • 9,972
  • 7
  • 57
  • 66
myx
  • 1,063
  • 10
  • 16
  • Also worked for me. Just make sure to use this before setting limits/ticks, as it will rescale automatically. – Andrew May 27 '19 at 12:09
  • 8
    Sorry, plt.axis('scaled') didn't work for me in Python 3.7 and matplotlib - matplotlib==3.1.0 However, plt.axis('square') worked! – rishi jain Oct 11 '19 at 10:15
  • @rishijain ValueError: Unrecognized string squared to axis; try on or off – Mona Jalal Jan 21 '22 at 18:54
57

See the documentation on plt.axis(). This:

plt.axis('equal')

doesn't work because it changes the limits of the axis to make circles appear circular. What you want is:

plt.axis('square')

This creates a square plot with equal axes.

Adam Stewart
  • 1,700
  • 1
  • 15
  • 14
22

Try something like:

import pylab as p
p.plot(x,y)
p.axis('equal')
p.show()
Dman2
  • 670
  • 4
  • 10
  • This works on my system, perhaps you could show a portion of the code you are working on? Might be able to help work out the issue quicker. – Dman2 Aug 01 '13 at 15:27
  • This does NOT work in general. The axes are equal, but the plot is not square, unless the plotting window is also square. Tested with Matplotlib 2.0 – divenex Apr 25 '17 at 21:19
  • 1
    `P.axis('equal')` seems to be like `P.gca().set_aspect('equal', adjustable='datalim')`. While if `adjustable='box'`, then the plot becomes square. – Evgeni Sergeev Jan 03 '18 at 09:22
  • 1
    I definitely do *not* get a square box out of this. – Peter Drake Apr 17 '19 at 15:58
  • pylab is deprecated – eric Jul 29 '20 at 13:46
  • If you want to also have the grid square, in addition to aspect as mentioned in the other answers, see https://stackoverflow.com/a/65049909/55935 – Giovanni Funchal Nov 29 '20 at 14:31
0

you can stretch the plot to square using this :

fig = plt.figure(figsize=(1, 1))
rzb
  • 21
  • 7