Reputation: 103
I want to have a row of subplots with the same aspect ratio. Let's say I want to plot two different functions that have different extents on the y axis.
There seem to be lots of questions on this but the examples seem to conveniently have the same axes for all subplots. In any case none that I found were helpful to me.
I've tried the following
import numpy as np
import matplotlib.pyplot as plt
xdata = np.arange(0,2,.01)
ydata1 = xdata
ydata2 = xdata ** 2
fig, ax = plt.subplots(1,2)
ax[0].plot(xdata,ydata1)
ax[1].plot(xdata,ydata2)
ax[0].set_aspect(.5)
ax[1].set_aspect(.5)
plt.show(fig)
However, matplotlib appears to be using the x and y axis data to determine the aspect ratio and because the y axes have different extents the subplots come out different. This is super weird to me. How do I make them the same physical aspect ratio?
I guess one can try extracting the the limits for each subplot and calculate the right aspect ratio individually but this seems to be a very roundabout way and I would expect such a basic functionality as making all subplots look the same to be built in.
EDIT So what I want is for both subplots to have the same aspect ratio in the human sense, that is that the ratio of the width of the figure to the height is the same for both. For example in Mathematica I would achieve this by simply setting the AspectRatio
attribute:
xdata = Range[0, 2, .01];
ydata1 = {#, #} & /@ xdata;
ydata2 = {#, #^2} & /@ xdata;
fig = GraphicsRow[
ListLinePlot[#, AspectRatio -> 1/GoldenRatio, Frame -> True,
ImageSize -> 300] & /@ {ydata1, ydata2}];
Export["fig.png", fig]
Upvotes: 1
Views: 4658
Reputation: 339052
The question isn't entirely clear on what the desired outcome is. Possibly you want to have a fixed data aspect with out changing the axes?
import numpy as np
import matplotlib.pyplot as plt
xdata = np.arange(0,2,.01)
ydata1 = xdata
ydata2 = xdata ** 2
fig, ax = plt.subplots(1,2)
ax[0].plot(xdata,ydata1)
ax[1].plot(xdata,ydata2)
ax[0].set_aspect(.5, adjustable="datalim")
ax[1].set_aspect(.5, adjustable="datalim")
plt.show()
Upvotes: 1
Reputation: 629
Short answer: use the figsize keyword argument when making subplots:
import numpy as np
import matplotlib.pyplot as plt
xdata = np.arange(0,2,.01)
ydata1 = xdata
ydata2 = xdata ** 2
fig = plt.figure(figsize=(10,6))
ax = fig.subplots(1,2)
ax[0].plot(xdata,ydata1)
ax[1].plot(xdata,ydata2)
# Squares
ax[0].plot([0,1,1,0],[0,0,1,1])
ax[1].plot([0,1,1,0],[0,0,1,1])
plt.show(fig)
figsize
is a tuple in inches, with the first element as the width in the x-direction, the second element as the width in the y-direction.
It applies to the whole figure; you will need to tweak it to get a suitable shape for your subplots.
Longer answer: .set_aspect(num)
sets the y-axis to x-axis ratio for each plot.
So, when you used .set_aspect(.5)
on each axis, you told matplotlib
to reconfigure each axis such that the y-axis is 0.5 times as big as the x-axis. This means that a 1x1 square actually looks like a rectangle on each plot:
import numpy as np
import matplotlib.pyplot as plt
xdata = np.arange(0,2,.01)
ydata1 = xdata
ydata2 = xdata ** 2
fig, ax = plt.subplots(1,2)
ax[0].plot(xdata,ydata1)
ax[1].plot(xdata,ydata2)
# Squares
ax[0].plot([0,1,1,0],[0,0,1,1])
ax[1].plot([0,1,1,0],[0,0,1,1])
ax[0].set_aspect(.5)
ax[1].set_aspect(.5)
plt.show(fig)
That's why your plots are different shapes; the axis limits are different, but you've set the size of shapes on both plots to be the same.
Upvotes: 2