I am trying to create a plot with equal grid spacing the first code I used is:
import numpy as np
import matplotlib.pyplot as plt
time= np.linspace (0, 25, 5000)
temp_pri = 50 / np.sqrt (2 * np.pi * 3**2) * np.exp (-((time - 13)**2 / (3**2))**2) + 15
temp_sec = 50 * np.sin(2* np.pi * time/100)
figure_x_y = plt.figure(figsize=(10, 10))
figure_x_y.clf()
plot_x_vs_y = plt.subplot(111)
plot_x_vs_y.plot(time, temp_pri, linewidth=1.0)
plot_x_vs_y.set_ylabel(r'\textit{Temperature (K)}', labelpad=6)
plot_x_vs_y.set_xlabel(r'\textit{Time (ms)}', labelpad=6)
# plot_x_vs_y.set_aspect('equal')
ax2 = plot_x_vs_y.twinx()
ax2.plot(time, temp_sec, color='#4DAF4A')
# ax2.set_aspect('equal')
plt.show()
plt.close()
and the output is I get is:
When I set the option set_aspect('equal') option on, code:
import numpy as np
import matplotlib.pyplot as plt
time= np.linspace (0, 25, 5000)
temp_pri = 50 / np.sqrt (2 * np.pi * 3**2) * np.exp (-((time - 13)**2 / (3**2))**2) + 15
temp_sec = 50 * np.sin(2* np.pi * time/100)
figure_x_y = plt.figure(figsize=(10, 10))
figure_x_y.clf()
plot_x_vs_y = plt.subplot(111)
plot_x_vs_y.plot(time, temp_pri, linewidth=1.0)
plot_x_vs_y.set_ylabel(r'\textit{Temperature (K)}', labelpad=6)
plot_x_vs_y.set_xlabel(r'\textit{Time (ms)}', labelpad=6)
plot_x_vs_y.set_aspect('equal')
ax2 = plot_x_vs_y.twinx()
ax2.plot(time, temp_sec, color='#4DAF4A')
ax2.set_aspect('equal')
plt.show()
plt.close()
the output I get is:
How can I get both (primary and secondary y-axis) the grid spacing to be the same?
If by "the same spacing" you mean that numbers on both y-axises are aligned then you could use .ylim()
to set min/max ticks on both of the axises:
#plot_x_vs_y.set_ylim(10,25) # This one is optional, manually set min/max for primary axis.
lims = plot_x_vs_y.get_ylim() # Get min/max of primary y-axis
ax2.set_ylim(lims) # Set min/max of secondary y-axis
ax2.grid('off') # You can turn the grid of secondary y-axis off
plt.show()
This gives:
UPDATE:
To allow more flexibility here is a helper function that you might call just before calling plt.show()
:
def align_axis(ax1, ax2, step=1):
""" Sets both axes to have the same number of gridlines
ax1: left axis
ax2: right axis
step: defaults to 1 and is used in generating a range of values to check new boundary
as in np.arange([start,] stop[, step])
"""
ax1.set_aspect('auto')
ax2.set_aspect('auto')
grid_l = len(ax1.get_ygridlines()) # N of gridlines for left axis
grid_r = len(ax2.get_ygridlines()) # N of gridlines for right axis
grid_m = max(grid_l, grid_r) # Target N of gridlines
# Choose the axis with smaller N of gridlines
if grid_l < grid_r:
y_min, y_max = ax1.get_ybound() # Get current boundaries
parts = (y_max - y_min) / (grid_l - 1) # Get current number of partitions
left = True
elif grid_l > grid_r:
y_min, y_max = ax2.get_ybound()
parts = (y_max - y_min) / (grid_r - 1)
left = False
else:
return None
# Calculate the new boundary for axis:
yrange = np.arange(y_max + 1, y_max * 2 + 1, step) # Make a range of potential y boundaries
parts_new = (yrange - y_min) / parts # Calculate how many partitions new boundary has
y_new = yrange[np.isclose(parts_new, grid_m - 1)] # Find the boundary matching target
# Set new boundary
if left:
return ax1.set_ylim(top=round(y_new, 0), emit=True, auto=True)
else:
return ax2.set_ylim(top=round(y_new, 0), emit=True, auto=True)
So calling it on your example:
align_axis(plot_x_vs_y, ax2)
plt.show()
produces:
Which is perhaps a more fair representation than a cropped version of the plot.
Note that I have not tested it extensively and there might be extreme cases when this function will fail to find correct values for alignment.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.