How do you limit the y-axis height in matplotlib? - python

How do you limit the height of the y-axis in matplotlib figure? I am trying to both display the x axis, and reduce the height of the figure for this 1D plot.
I have tried setting ticks, figure sizes, tight_layout, margin, etc. with no luck.
Also, changing the ylimits just spans the full figure height no matter what limits I choose.
import numpy as np
import matplotlib.pyplot as plot
from matplotlib import rcParams
x = np.array([3500])
y = np.array([0])
rcParams['toolbar'] = 'None'
plot.figure(num=None, figsize=(4, 1), dpi=80, facecolor='w')
plot.axes(frameon=False)
plot.yticks([0])
plot.xlim(0, 6000)
plot.ylim(-0.1, 0.1)
plot.plot(x, y, 'x', markersize=10)
plot.show()
Current figure:
Desired figure:

Try this:
plot.ylim(lower_limit, upper_limit)
Where lower_limit is the value you want to set for the bottom of the y-axis and upper_limit is the value for the top.
np.random.seed(0)
x = np.random.randn(100)
y = np.random.randn(100)
plot.figure(num=None, figsize=(4, 1), dpi=80, facecolor='w')
plot.axes(frameon=False)
plot.ylim(-10, 10)
plot.plot(x, y, '.')

The code in the question already produces the desired result, when adding
plot.tight_layout() at the end.
Of course decreasing figure size even further, shrinks the plot even more. E.g.
figsize=(4, 0.7)

Simply changing figsize to (4, 0.3), I get something that more or less looks like your desired output (except with ticks at the top as well, but those can also be removed):

Related

matplotlib: equal axes and 0/0 at lower left corner

I would like to plot some data in an equal-spaced plot like this:
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(0, 10)
y = 2 * x
plt.figure(figsize=(2, 3), dpi=100)
plt.scatter(x, y)
plt.axline((0,0), slope=1, linestyle=':')
plt.gca().set_aspect('equal', 'datalim')
In this example, the origin (0/0) is in the lower left corner and the 1:1 line passes right through the corner.
However, if I change the size of the figure just slightly, either the x or y axis will start on a different location:
plt.figure(figsize=(4, 3), dpi=100)
plt.scatter(x, y)
plt.axline((0,0), slope=1, linestyle=':')
plt.gca().set_aspect('equal', 'datalim')
Is it possible to enforce both an equal spacing on both axes but also keep the origin (in my case always 0/0) in the lower left corner?
Setting the limits on the x and y axis using plt.xlim and plt.ylim should solve the problem
checkout https://matplotlib.org/3.5.1/api/_as_gen/matplotlib.pyplot.xlim.html

Matplotlib: How can I show only exponents in the y tick labels of a semi-log plot with secondary_yaxis()?

I've been working on matplotlib's secondary-yaxis and I can't figure out how I should set "functions" parameter in order to get the result that I want.
I want to make a semi-log plot and set set the labels of y-ticks in the 2 following formats:
ordinary format such as "10^1, 10^2, 10^3, ..., 10^(exponent), ..."
the exponents only: "1, 2, 3, ..."
And I want to put them in the former style in the y-axis of left side, and the latter right side.
What I want to do can be done by using twinx() like this:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(1, 3, 41)
y = 10**x
fig, ax1 = plt.subplots()
ax1.set_yscale('log')
ax1.plot(x, y)
ax2 = ax1.twinx()
ymin, ymax = ax1.get_ylim()
ax2.set_ylim(np.log10(ymin), np.log10(ymax))
plt.show()
You would see that i=(1, 2, 3) in the right label is located at the same height as 10^i in the left label.
However, I want to know how to do the same thing by secondary_yaxis. I've tried this but it didn't work.
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(1, 3, 41)
y = 10**x
fig, ax = plt.subplots()
ax.set_yscale('log')
ax.plot(x, y)
def forward(x):
return np.log10(x)
def backward(x):
return 10**x
secax = ax.secondary_yaxis('right', functions=(forward, backward))
plt.show()
It resulted in this:
You can see right-side tick labels are broken. I suspect that my way of setting the parameter "functions" of secondary_yaxis() might be invalid. I would appreciate it if you tell me how to do it.
I get the broken figure on matplotlib 3.1.0. and updating it to 3.3.0. has solved the problem. The same code as the second code block of the question generates this.
enter image description here

How can I control the number of tick labels for an axis in logarithm scale with matplotlib?

I am trying to make a figure with a few subplots, where the x axis for some of them were set to logarithm scale. However, the tick labels are getting crowded and I have no idea of how to reduce the number of tick labels.
I tried matplotlib.pyplot.locator_params(axis = 'x', nbins = 2) but it does not work for axises in logarithm scale, I also tried
x_tick_locations = matplotlib.ticker.LogLocator(numticks = 2)
ax.xaxis.set_major_locator(x_tick_locations)
but get no luck. I know I can always manipulate by hand, but there are many subplots and I prefer a automated way of doing this.
Is there a way to limit number of tick labels for an axis in logarithm scale?
Thanks in advance!
I don't have much experience with this type of graph, but I've customized the information from the official website to A sample was created for setting the x-axis range with plt.xlim(). The setting information was based on SO answer.
import matplotlib.pyplot as plt
import numpy as np
# fig, ax = plt.subplots()
fig = plt.figure(figsize=(8,4),dpi=144)
dt = 0.01
t = np.arange(dt, 20.0, dt)
ax1 = plt.subplot(211)
ax1.semilogx(t, np.exp(-t / 5.0))
ax1.grid()
ax2 = plt.subplot(212, sharex=ax1)
ax2.loglog(t, 20 * np.exp(-t / 10.0), basex=10)
ax1.grid()
# Changing the x-axis range
plt.xlim([1, 10**2])
plt.show()
Graph before setting parameters:
Graph after setting parameters:

Preserve padding while setting an axis limit in matplotlib

Setting xlim and ylim for axis in pyplot removes the padding. How to set them without changing the padding?
Example:
fig, ax = plt.subplots()
x = np.linspace(0, 200, 500)
ax.set_ylim(ymax=100)
line = ax.plot(x, data, '--', linewidth=2, label='foo bar')
plt.show()
In the plot shown, x axis will have a padding while y axis don't. How to make them both have padding while having the ylim I want?
Axes.set_ymargin and Axes.set_ylim are mutually exclusive. Setting a limit to an axis overwrites the margin.
There are two options to have a margin (padding).
a. use margins
It's possible to adapt the margin using
ax.set_ymargin(0.1) or ax.margins(y=0.1)
where 0.1 would be a 10% margin on both axis ends. (Same for x axis of course). The drawback here is that the margin is always symmetric.
b. use limits
Using the limits set by ax.set_ylim(0, 100) and adapt them to the needs.
E.g. if data is the data to plot in form of a numpy array, and we want to have a 10% margin to the bottom and a 40% margin to the top, we could use
ymin = data.min()-0.1*(data.max()-data.min())
ymax = data.max()+0.4*(data.max()-data.min())
ax.set_ylim((ymin, ymax))
It would of course equally be possible to simply set ymax to ymax = 100, if this is desired.
With matplotlib 3.5, I used autoscaling as follows;
axs[row,column].plot(divs['Dividends'], c='red',linewidth=1, marker='.', mec='blue',mfc='blue')
axs[row,column].set_ylim(bottom = 0)
axs[row,column].autoscale()
Solved this problem for me. See attached pics of the graphs for the difference autoscaling did.
Using .margins() with a value or 'tight=True' or .set_ymargin() didn't seem to do anything no matter what values I used to pad.
Changing the lower or bottom limit to <0 moved the Zero line well up the y axis when dividends in my examples are close to zero.
Graph with Autoscaling
Graph without Autoscaling
You can modify the ax.dataLim bounding box and reapply ax.autoscale_view()
Before:
fig, ax = plt.subplots()
x = np.linspace(0, 10, 11)
line = ax.plot(x, x, '--', linewidth=2, label='foo bar')
After:
pts = ax.dataLim.get_points() # numpy array [[xmin, ymin], [xmax, ymax]]
pts[1, 1] = 11 # new ymax
ax.dataLim.set_points(pts)
ax.autoscale_view()

tick label positions for matplotlib 3D plot

I am trying to work out how to set/correct the position of tick labels for a 3D matplotlib plot. Tick labels do not align with the ticks. The issue seems to be especially prominent when many tick labels are required.
I have modified an example (http://matplotlib.org/examples/mplot3d/polys3d_demo.html) from the matplotlib documentation to illustrate my question.
from mpl_toolkits.mplot3d import Axes3D
from matplotlib.collections import PolyCollection
from matplotlib.colors import colorConverter
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure(figsize=(10,10))
ax = fig.gca(projection='3d')
cc = lambda arg: colorConverter.to_rgba(arg, alpha=0.6)
xs = np.arange(0, 10, 0.4)
verts = []
zs = np.arange(50)
for z in zs:
ys = np.ones(len(xs))*z
ys[0], ys[-1] = 0, 0
verts.append(list(zip(xs, ys)))
poly = PolyCollection(verts,facecolor='c')
poly.set_alpha(0.7)
ax.add_collection3d(poly, zs=zs, zdir='y')
ax.set_xlabel('X')
ax.set_xlim3d(0, 10)
ax.set_ylabel('Y')
ax.set_ylim3d(-1, len(zs))
ax.set_yticks(np.arange(len(zs)))
labels = {}
for l_c in zs:
labels[l_c] = 'This Looks Bad'
ax.set_yticklabels(labels,rotation=-15)
ax.set_zlabel('Z')
ax.set_zlim3d(0, ys.max())
plt.show()
So the question is: how can I get the tick labels to align with the tick positions?
By using these alignments, I get much better placements:
ax.set_yticklabels(labels,rotation=-15,
verticalalignment='baseline',
horizontalalignment='left')
I've modified the example with less tick markers so you can see the placement:
They do align, but with the horizontal position centered at the tick. Because of the 3D view this makes them appear a bit below where you would expect them to be. The effect is not related to the amount of ticks but to the width.
Specifically setting the alignment will help. Try adding:
ax.set_yticklabels(labels,rotation=-15, va='center', ha='left')
Play around a bit with the different alignments to see which you prefer, i think you're after ha='left'.
Reducing the padding, distance from the tick, might also help.
You can also set the pad argument as negative in the tick_params options for each axis. Like this:
ax.tick_params(axis='x', which='major', pad=-3)
This might help to adjust the distance between tick labels and axis.

Categories

Resources