Changing nticks in subplots in matplotlib - python

Why is the number of ticks on the x and y axes not reduced to 3 in this example?
import numpy as np
import matplotlib.pyplot as plt
fig,ax=plt.subplots(nrows=4,ncols=3)
for n in range(0,4):
for f in range(0,3):
ax[n,f].plot(range(10), range(10,20))
ax[n,f].locator_params(axis='x', nticks=3)
ax[n,f].locator_params(axis='y', nticks=3)
fig.savefig('not_3_ticks.png')
I am left with the following figure:

This also works:
import numpy as np
import matplotlib.pyplot as plt
fig,ax = plt.subplots(nrows=4,ncols=3)
for n in range(0,4):
for f in range(0,3):
ax[n,f].plot(range(10), range(10,20))
ax[n,f].xaxis.set_major_locator(plt.MaxNLocator(3))
ax[n,f].yaxis.set_major_locator(plt.MaxNLocator(3))
plt.plot()
plt.show()
fig.savefig('yes_3_ticks.png')

The reason locator_params(axis='x', nticks=3) is not working as expected is that nticks is not a valid argument to the matplotlib.ticker.AutoLocator in use.
From the documentation:
Typically one might want to reduce the maximum number
of ticks and use tight bounds when plotting small
subplots, for example::
ax.locator_params(tight=True, nbins=4)
So replace nticks by nbins.

Related

How can force python matplotlib to axis to scale linearly?

So here is my python code.
import matplotlib.pyplot as plt
M=[]
for i in np.arange(0.01,8,0.01):
M.append(test(i))
plt.plot(M)
plt.grid(b=True,which="major",color='#666666', linestyle='-',linewidth=0.2)
plt.show()
Where test(x) is some complicated function.
When i try to plot it python for some plots on X-axis from 1 to 800, but i want have scaled it plot from 0.01 to 8. So scaled down without changing graph.
Due to complicated form of test(x) function, i would like to use arrays, and this method of ploting.
Add an index to plot against (essentially your x-axis values):
import matplotlib.pyplot as plt
M=[]
indices = []
for i in np.arange(0.01,8,0.01):
M.append(test(i))
indices.append(i)
plt.plot(indices, M)
plt.grid(b=True,which="major",color='#666666', linestyle='-',linewidth=0.2)
plt.show()

I'm attempting to plot the square roots in a single figure. However this is not getting plotted

I'm attempting to plot the square roots in a single figure. However, this is not getting plotted. Can somebody help me?
import numpy as np
import matplotlib.pyplot as plt
plt.figure()
for i in np.arange(1,5):
zm=i**2
plt.plot(i,zm,'r')
print(i,zm)
plt.show()
A few issues with your code:
zm should be an array, but instead it is an integer that gets overwritten every cycle with the return of i**2,
The plot() instruction should be outside the loop,
You don't really need the for loop, you can do the square of the array with the ** operator.
I guess this is what you are looking for:
import numpy as np
import matplotlib.pyplot as plt
xx = np.arange(1, 5)
zm = xx**2
plt.figure()
plt.plot(xx,zm,'r')
plt.show()
BTW, I believe you meant square and not square root.
I hope it helps.

plotting vertical bars instead of points, plot_date

I want to plot vertical bars instead of points. The actual data I have are irregularly spaced, so this will help visualize gaps more easily.
When I try to plot it, the best I can do are points, which don't increase in size as you zoom in!
import matplotlib
from matplotlib import pyplot as plt
import datetime
XX = [datetime.date.today()+datetime.timedelta(x) for x in range(10)]
YY = range(10)
plt.plot_date(XX,YY,'o')
Any ideas on how I can make taller/bigger (but not wider!) points?
You can use ax.vlines to plot a collection of vertical lines.
You can adjust ymin and ymax to suit your data.
import matplotlib
from matplotlib import pyplot as plt
import datetime
XX = [datetime.date.today()+datetime.timedelta(x) for x in range(10)]
plt.vlines(XX, ymin=0, ymax=1, linewidth=5)
plt.show()
Did you mean bars like this?
And here is the code:
import matplotlib
from matplotlib import pyplot as plt
import datetime
XX = [datetime.date.today()+datetime.timedelta(x) for x in range(10)]
YY = range(10)
plt.plot_date(XX,YY,'|')
plt.show()
You can change the shape of your plot by changing the third argument you pass in the plt.plot_date function.
In your code you are passing an 'o' that is why you get a dot. Here i pass bar to plot bar.

set constant width to every bar in a bar plot

I am trying to plot a bar plot where each bin has a difference length and as a result I end up with a very ugly result.c:) What I would like to do is still be able to define a bin of deference lengths but all the bars be plotted the same fixed width. How can I do that? Here is what I have done so far:
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
sns.set_palette("deep", desat=.6)
sns.set_context(rc={"figure.figsize": (8, 4)})
np.random.seed(9221999)
data = [0,2,30,40,50,10,50,40,150,70,150,10,3,70,70,90,10,2]
bins = [0,1,2,3,4,5,6,7,8,9,10,20,30,40,50,60,70,80,90,100,200]
plt.hist(data, bins=bins);
EDIT
This question has been marked as duplicate but in fact non of the proposed links solved my problem; the 1st is a very crappy workaround and the 2nd doesn't solve the problem at all as it sets all bars' width to a certain number.
Here you go, with seaborn, as you please. But you have to understand that seaborn itself uses matplotlib to create plots.
AND: Please delete your other question, now it really is a duplicate.
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
sns.set_palette("deep", desat=.6)
sns.set_context(rc={"figure.figsize": (8, 4)})
data = [0,2,30,40,50,10,50,40,150,70,150,10,3,70,70,90,10,2]
bins = [0,1,2,3,4,5,6,7,8,9,10,20,30,40,50,60,70,80,90,100,200]
bin_middles = bins[:-1] + np.diff(bins)/2.
bar_width = 1.
m, bins = np.histogram(data, bins)
plt.bar(np.arange(len(m)) + (1-bar_width)/2., m, width=bar_width)
ax = plt.gca()
ax.set_xticks(np.arange(len(bins)))
ax.set_xticklabels(['{:.0f}'.format(i) for i in bins])
plt.show()
Personally I think, that plotting your data like this is confusing. Having non-linear (or non-log) axis scaling is usually not a good idea.
Are you wanting to place a bar with a fixed width at the center of each bin?
If so, try something something similar to this:
import numpy as np
import matplotlib.pyplot as plt
data = [0,2,30,40,50,10,50,40,150,70,150,10,3,70,70,90,10,2]
bins = [0,1,2,3,4,5,6,7,8,9,10,20,30,40,50,60,70,80,90,100,200]
counts, _ = np.histogram(data, bins)
centers = np.mean([bins[:-1], bins[1:]], axis=0)
plt.bar(centers, counts, width=5, align='center')
plt.show()

PyLab: Plotting axes to log scale, but labelling specific points on the axes

Basically, I'm doing scalability analysis, so I'm working with numbers like 2,4,8,16,32... etc and the only way graphs look rational is using a log scale.
But instead of the usual 10^1, 10^2, etc labelling, I want to have these datapoints (2,4,8...) indicated on the axes
Any ideas?
There's more than one way to do it, depending on how flexible/fancy you want to be.
The simplest way is just to do something like this:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
x = np.exp2(np.arange(10))
plt.semilogy(x)
plt.yticks(x, x)
# Turn y-axis minor ticks off
plt.gca().yaxis.set_minor_locator(mpl.ticker.NullLocator())
plt.show()
If you want to do it in a more flexible manner, then perhaps you might use something like this:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
x = np.exp2(np.arange(10))
fig = plt.figure()
ax = fig.add_subplot(111)
ax.semilogy(x)
ax.yaxis.get_major_locator().base(2)
ax.yaxis.get_minor_locator().base(2)
# This will place 1 minor tick halfway (in linear space) between major ticks
# (in general, use np.linspace(1, 2.0001, numticks-2))
ax.yaxis.get_minor_locator().subs([1.5])
ax.yaxis.get_major_formatter().base(2)
plt.show()
Or something like this:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
x = np.exp2(np.arange(10))
fig = plt.figure()
ax = fig.add_subplot(111)
ax.semilogy(x)
ax.yaxis.get_major_locator().base(2)
ax.yaxis.get_minor_locator().base(2)
ax.yaxis.get_minor_locator().subs([1.5])
# This is the only difference from the last snippet, uses "regular" numbers.
ax.yaxis.set_major_formatter(mpl.ticker.ScalarFormatter())
plt.show()

Categories