Consider the illustrative example below:
from matplotlib import pyplot as plt
x=list(range(5))
xticks=x.copy()
xlabels=x.copy()
xlabels[-1] = r"$\infty$"
fig, axes = plt.subplots()
axes.plot(x)
axes.set_xticks(xticks)
axes.set_xticklabels(xlabels, fontsize=20)
This produces the following figure
I want to make the infinity sign larger in relation to the numbers in the x labels. It is too small in the way matplotlib plots it. Everything that I've tried to increase its size also increases the sizes of the numbers in the label.
How can I do that?
Thanks
Try this, grab the last element in the xticklabels array and use set_fontsize on that element:
from matplotlib import pyplot as plt
x=list(range(5))
xticks=x.copy()
xlabels=x.copy()
xlabels[-1] = r"$\infty$"
fig, axes = plt.subplots()
axes.plot(x)
axes.set_xticks(xticks)
axes.set_xticklabels(xlabels, fontsize=20)
axes.get_xticklabels()[-1].set_fontsize(26)
plt.show()
Output:
Related
I do have a question with matplotlib in python. I create different figures, where every figure should have the same height to print them in a publication/poster next to each other.
If the y-axis has a label on the very top, this shrinks the height of the box with the plot. So I use MaxNLocator to remove the upper and lower y-tick. In some plots, I want to have the 1.0 as a number on the y-axis, because I have normalized data. So I need a solution, which expands in these cases the y-axis and ensures 1.0 is a y-Tick, but does not corrupt the size of the figure using tight_layout().
Here is a minimal example:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import MaxNLocator
x = np.linspace(0,1,num=11)
y = np.linspace(1,.42,num=11)
fig,axs = plt.subplots(1,1)
axs.plot(x,y)
locator=MaxNLocator(prune='both',nbins=5)
axs.yaxis.set_major_locator(locator)
plt.tight_layout()
fig.show()
Here is a link to a example-pdf, which shows the problems with height of upper boxline.
I tried to work with adjust_subplots() but this is of no use for me, because I vary the size of the figures and want to have same the font size all the time, which changes the margins.
Question is:
How can I use MaxNLocator and specify a number which has to be in the y-axis?
Hopefully someone of you has some advice.
Greetings,
Laenan
Assuming that you know in advance how many plots there will be in 1 row on a page one way to solve this would be to put all those plots into one figure - matplotlib will make sure they are alinged on axes:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import MaxNLocator
x = np.linspace(0, 1, num=11)
y = np.linspace(1, .42, num=11)
fig, (ax1, ax2) = plt.subplots(1,2, figsize=(8,3), gridspec_kw={'wspace':.2})
ax1.plot(x,y)
ax2.plot(x,y)
locator=MaxNLocator(prune='both', nbins=5)
ax1.yaxis.set_major_locator(locator)
# You don't need to use tight_layout and using it might give an error
# plt.tight_layout()
fig.show()
I have a time series which will have over 10,000 daily values of a variable over the course of a year array size (365, 10000). Because I will have so much data (many time series for many variables), I was hoping to save only the percentiles (0, 10, 20,..., 90, 100) and use these later in plots to set a color gradient showing the density of values (obviously being darkest at the median and lightest at the min and max). The purpose of this is to avoid excessive file sizes in the saved simulation outputs, since I'll have millions of outputs to process. This would reduce the file sizes significantly if I can get it to work.
I was able to compute the percentiles of a sample data set (just using 50 values for now) and plot them as shown in the attached figure (using an array with size 365,11). How would I use this information to then set up a plot showing the colour gradient (or density of values)? Is this possible? Or is there some other way of going about it? I'm using matplotlib...
import numpy as np
import matplotlib.pyplot as plt
SampleData=(375-367)*np.random.random_sample((365, 50))+367
SDist=np.zeros((365,11))
for i in range(11):
for t in range(365):
SDist[t,i]=np.percentile(SampleData[t,:],i*10)
fig, (ax1) = plt.subplots(nrows=1, ncols=1, sharex=True, figsize=(8,4))
ax1.plot(np.arange(0,365,1), SDist)
ax1.set_title("SampleData", fontsize=15)
ax1.tick_params(labelsize=11.5)
ax1.set_xlabel('Day', fontsize=14)
ax1.set_ylabel('SampleData', fontsize=14)
fig.tight_layout()
EDIT
Here is a good example of what I'm going for (though obviously it will look different with my sample data) - I think it's similar to a fan chart:
You can use a matplotlib cm object to get the colormaps and manually calculate the color to plot based on a value. The below example calculates the color to plot based on line index (0-11). However, you can calculate the color based on anything, such as number of observations used to calculate the percentile, so long as you plot them individually and call the correct color value.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm
n = 11 # change this value for the number of iterations/percentiles
colormap = cm.Blues # change this for the colormap of choice
percentiles = np.linspace(0,100,n)
SampleData=(375-367)*np.random.random_sample((365, 50))+367
SDist=np.zeros((365,n))
for i in range(n):
for t in range(365):
SDist[t,i]=np.percentile(SampleData[t,:],percentiles[i])
half = int((n-1)/2)
fig, (ax1) = plt.subplots(nrows=1, ncols=1, sharex=True, figsize=(8,4))
ax1.plot(np.arange(0,365,1), SDist[:,half],color='k')
for i in range(half):
ax1.fill_between(np.arange(0,365,1), SDist[:,i],SDist[:,-(i+1)],color=colormap(i/half))
ax1.set_title("SampleData", fontsize=15)
ax1.tick_params(labelsize=11.5)
ax1.set_xlabel('Day', fontsize=14)
ax1.set_ylabel('SampleData', fontsize=14)
fig.tight_layout()
The result should look like this:
fill_between ended up solving the problem:
import numpy as np
import matplotlib.pyplot as plt
SampleData=(375-367)*np.random.random_sample((365, 50))+367
SDist=np.zeros((365,11))
for i in range(11):
for t in range(365):
SDist[t,i]=np.percentile(SampleData[t,:],i*10)
x=np.arange(0,365,1)
fig, (ax1) = plt.subplots(nrows=1, ncols=1, sharex=True, figsize=(8,4))
ax1.set_color_cycle(['red'])
ax1.plot(x, SDist[:,5])
for i in range(6):
alph=0.05+(i/10.)
ax1.fill_between(x, SDist[:,0+i], SDist[:,10-i], color="red", alpha=alph)
ax1.set_title("SampleData", fontsize=15)
ax1.tick_params(labelsize=11.5)
ax1.set_xlabel('Day', fontsize=14)
ax1.set_ylabel('SampleData', fontsize=14)
fig.tight_layout()
I'm plotting a figure and hope to set the figure shape and tick positions. But I find that I cannot do the two things together. For example, if I use the following code:
import matplotlib
import matplotlib.pyplot as plt
ls = range(0,10)
fig, ax = plt.subplots()
# set figure shape
plt.figure(figsize=(10,5))
plt.ylim([0,10])
plt.plot(ls)
figname = 'aaa.jpg'
# set ytick positions
ax.set_yticks([1,3,5,7,9])
plt.savefig(figname,format='jpg')
Then I get the following figure.
The shape is correct. But the ytick is not changed by the code line ax.set_yticks([1,3,5,7,9]).
Then I try the following code (i.e. move the sentence plt.figure(figsize=(10,5)) to the beginning of the program):
import matplotlib
import matplotlib.pyplot as plt
# set figure shape
plt.figure(figsize=(10,5))
ls = range(0,10)
fig, ax = plt.subplots()
plt.ylim([0,10])
plt.plot(ls)
figname = 'aaa.jpg'
# set ytick position
ax.set_yticks([1,3,5,7,9])
plt.savefig(figname,format='jpg')
Then I get the following figure:
The ytick is correct. Yicks appear in positions [1,3,5,7,9]. However, the figure shape is not the shape I set.
How to do the two things together?
Thank you all for helping me!!!
you can set the figsize in the subplot function instead.
what went wrong in the first graph:
plt.figure(figsize=(10,5))
the above line of code is creating a new figure on which your graph is being plotted, the 'ax' on which you are setting the y ticks is related to a subplot which is different.
ls = range(0,10)
fig, ax = plt.subplots(figsize=(10,5))
ax.set_yticks([1,3,5,7,9])
ax.set_xticks([1,3,5,7,9])
plt.grid()
plt.plot(ls)
The plot is showing exactly what you're trying to do
I do have a question with matplotlib in python. I create different figures, where every figure should have the same height to print them in a publication/poster next to each other.
If the y-axis has a label on the very top, this shrinks the height of the box with the plot. So I use MaxNLocator to remove the upper and lower y-tick. In some plots, I want to have the 1.0 as a number on the y-axis, because I have normalized data. So I need a solution, which expands in these cases the y-axis and ensures 1.0 is a y-Tick, but does not corrupt the size of the figure using tight_layout().
Here is a minimal example:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import MaxNLocator
x = np.linspace(0,1,num=11)
y = np.linspace(1,.42,num=11)
fig,axs = plt.subplots(1,1)
axs.plot(x,y)
locator=MaxNLocator(prune='both',nbins=5)
axs.yaxis.set_major_locator(locator)
plt.tight_layout()
fig.show()
Here is a link to a example-pdf, which shows the problems with height of upper boxline.
I tried to work with adjust_subplots() but this is of no use for me, because I vary the size of the figures and want to have same the font size all the time, which changes the margins.
Question is:
How can I use MaxNLocator and specify a number which has to be in the y-axis?
Hopefully someone of you has some advice.
Greetings,
Laenan
Assuming that you know in advance how many plots there will be in 1 row on a page one way to solve this would be to put all those plots into one figure - matplotlib will make sure they are alinged on axes:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import MaxNLocator
x = np.linspace(0, 1, num=11)
y = np.linspace(1, .42, num=11)
fig, (ax1, ax2) = plt.subplots(1,2, figsize=(8,3), gridspec_kw={'wspace':.2})
ax1.plot(x,y)
ax2.plot(x,y)
locator=MaxNLocator(prune='both', nbins=5)
ax1.yaxis.set_major_locator(locator)
# You don't need to use tight_layout and using it might give an error
# plt.tight_layout()
fig.show()
Is there a simple way to make matplotlib not show the powers of ten in a log plot, and instead just show the numbers? I.e., instead of [10^1, 10^2, 10^3] display [10, 100, 1000]? I don't want to change the tickmark locations, just want to get rid of the powers of ten.
This is what I currently have:
I can change the labels themselves via xticks, however I then get mismatching fonts or sizes for the y tick labels. I am using TeX for this text. I've tried the following:
xx, locs = xticks()
ll = [r'\rm{%s}' % str(a) for a in xx]
xticks(xx, ll)
This gives the following result:
In this particular case, I could use the same LaTeX roman font, but the sizes and looks are different to those in the y axis. Plus, if I used a different LaTeX font in matplotlib this is going to be problematic.
Is there a more flexible way of switching off the power of ten notation?
Use a ScalarFormatter:
from matplotlib import rc
rc('text', usetex=True)
rc('font', size=20)
import matplotlib.pyplot as plt
from matplotlib.ticker import ScalarFormatter
fig = plt.figure(figsize=(10, 6))
ax = fig.add_subplot(111)
ax.semilogx(range(100))
ax.xaxis.set_major_formatter(ScalarFormatter())
plt.show()