How to add minor ticks on a matplotlib plot - python

I want to add minor ticks on the y axis. I tried several methods but they all seem to not work. The minor ticks just won't show up.
Here is my code.
sns.set_style('whitegrid')
dd.plot(x='Date', y='Min', lw = 4, figsize=(50,30), color = 'red')
plt.grid(color = 'grey')
dd['P05'].plot(lw = 2)
dd['P10'].plot(lw = 2)
dd['P25'].plot(lw = 2)
dd['P50'].plot(lw = 2)
dd['P75'].plot(lw = 2)
dd['P90'].plot(lw = 2)
dd['P95'].plot(lw = 2)
dd['Max'].plot(lw = 4, color = 'black')
plt.xticks(np.arange(0,366, step=31), list(monthDict.values()),\
fontsize = 35, fontname = 'Consolas')
plt.yticks(fontsize = 35)
plt.ylabel('Daily Average Stage (ft NGVD29)', fontsize = 35, \
labelpad = 25,fontname = 'Consolas', color = 'black')
plt.xlabel('') #remove xlabel
plt.legend(prop={'family':'Consolas', 'size':35})
# plt.legend(['5th Pecrentile', '10th percentile', '25th percentile', \
# '50th percentile', '75th percentile', '90th percentile', \
# '95th percentile', '99th percentile'])
plt.title('Cyclic Analysis at {}-H'.format(x),\
fontsize = 55, fontname='Consolas', color = 'black')
ax.minorticks_on()
ax.tick_params(axis='y', which='minor', bottom=False)
I would like to get both the major and minor y ticks at the end of the plot

You can try this
ax.yaxis.get_ticklocs(minor=True)
ax.minorticks_on()
If you want to disable the minor ticks on the x-axis, you can do
ax.xaxis.set_tick_params(which='minor', bottom=False)
Based on #spinup's answer: how to turn on minor ticks only on y axis matplotlib

Related

Matplotlib Obscure Tick Behaviour

I observe some obscure behaviour of the ticks in a matplotlib.pyplot log-log plot.
#!/usr/bin/python3
import matplotlib.pyplot as plt
import matplotlib
import numpy as np
dtFractions = [1/1, 1/2, 1/4, 1/8]
L2Err = [4.41669808e-06, 1.10121946e-06, 2.78272254e-07, 8.18570087e-08]
LInfErr = [7.68589519e-05, 2.00625677e-05, 6.05176778e-06, 2.55658820e-06]
InchesX = 7
fig, ax = plt.subplots()
Blue_RGB = [(0, 84/256, 159/256)]
Petrol_RGB = [(0/256, 152/256, 161/256)]
### ACTUAL PLOTTING: Infty errors ###
ax.scatter(dtFractions, LInfErr, label = r'$e^\infty$', color = Blue_RGB)
ax.plot(dtFractions, LInfErr, color = Blue_RGB[0], linestyle='dashed')
ax.scatter(dtFractions, L2Err, label = r'$e^2$', color = Petrol_RGB)
ax.plot(dtFractions, L2Err, color = Petrol_RGB[0], linestyle='dashed')
ax.loglog(dtFractions, np.multiply(1e-5, np.power(dtFractions, 2) ), linestyle='dotted',
label = r'$\mathcal{O}\left(\Delta t^2\right)$',
color = 'black') # Order two line fitted
# Turn on logscale (no native support for logarithmic scatter)
ax.set_yscale('log')
ax.set_xscale('log')
ax.set_xlabel(r'$\Delta t^\mathrm{Eff}_S$')
### GRID SECTION ###
ax.grid(axis ='both', which='major', alpha=0.1, linewidth = 1.5, color ='black')
ax.set_axisbelow(True) # Hide grid behind bars
### LEGEND SECTION ###
ax.legend(loc = "upper left")
### TICKS SECTION ###
plt.tick_params(axis='x', which = 'both', bottom=False)
ax.set_xticks(dtFractions)
ax.get_xaxis().set_major_formatter(matplotlib.ticker.ScalarFormatter())
ax.get_xaxis().set_tick_params(which='minor', size=0)
ax.get_xaxis().set_tick_params(which='minor', width=0)
ax.set_xticklabels([r"$1$", r"$1/2$", r"$1/4$", r"$1/8$"])
### TITLE SECTION ###
plt.title(r"$l^\infty$ Error for CEE: Isentropic Vortex on Uniform Grid")
# Scale while preserving aspect ratio
width, height = fig.get_size_inches()
factor = InchesX / width
fig.set_size_inches(width * factor, height * factor)
plt.tight_layout() # Title, labels, ... to screen
plt.savefig('Convergence2DComprEulerVortex_PERK.pgf', bbox_inches = 'tight', pad_inches = 0)
plt.show()
This produces
Note in particular the strange additional ticks.
If I add one more custom tick, i.e.,
#!/usr/bin/python3
import matplotlib.pyplot as plt
import matplotlib
import numpy as np
dtFractions = [1/1, 1/2, 1/4, 1/8, 1/16]
L2Err = [4.41669808e-06, 1.10121946e-06, 2.78272254e-07, 8.18570087e-08, 42]
LInfErr = [7.68589519e-05, 2.00625677e-05, 6.05176778e-06, 2.55658820e-06, 42]
InchesX = 7
fig, ax = plt.subplots()
Blue_RGB = [(0, 84/256, 159/256)]
Petrol_RGB = [(0/256, 152/256, 161/256)]
### ACTUAL PLOTTING: Infty errors ###
ax.scatter(dtFractions, LInfErr, label = r'$e^\infty$', color = Blue_RGB)
ax.plot(dtFractions, LInfErr, color = Blue_RGB[0], linestyle='dashed')
ax.scatter(dtFractions, L2Err, label = r'$e^2$', color = Petrol_RGB)
ax.plot(dtFractions, L2Err, color = Petrol_RGB[0], linestyle='dashed')
ax.loglog(dtFractions, np.multiply(1e-5, np.power(dtFractions, 2) ), linestyle='dotted',
label = r'$\mathcal{O}\left(\Delta t^2\right)$',
color = 'black') # Order two line fitted
# Turn on logscale (no native support for logarithmic scatter)
ax.set_yscale('log')
ax.set_xscale('log')
ax.set_xlabel(r'$\Delta t^\mathrm{Eff}_S$')
### GRID SECTION ###
ax.grid(axis ='both', which='major', alpha=0.1, linewidth = 1.5, color ='black')
ax.set_axisbelow(True) # Hide grid behind bars
### LEGEND SECTION ###
ax.legend(loc = "upper left")
### TICKS SECTION ###
plt.tick_params(axis='x', which = 'both', bottom=False)
ax.set_xticks(dtFractions)
ax.get_xaxis().set_major_formatter(matplotlib.ticker.ScalarFormatter())
ax.get_xaxis().set_tick_params(which='minor', size=0)
ax.get_xaxis().set_tick_params(which='minor', width=0)
ax.set_xticklabels([r"$1$", r"$1/2$", r"$1/4$", r"$1/8$", r"$1/16$"])
### TITLE SECTION ###
plt.title(r"$l^\infty$ Error for CEE: Isentropic Vortex on Uniform Grid")
# Scale while preserving aspect ratio
width, height = fig.get_size_inches()
factor = InchesX / width
fig.set_size_inches(width * factor, height * factor)
plt.tight_layout() # Title, labels, ... to screen
plt.savefig('Convergence2DComprEulerVortex_PERK.pgf', bbox_inches = 'tight', pad_inches = 0)
plt.show()
Then everything works as expected:
Is this a bug? I tried also the second version and then setting xlim to something fitting - the obscure ticks are arising again.

Matplotlib.axes.Axes.bar conditional formatting

I have a vertical bar plot in matplotlib and would like the color of the bars to vary based on the values in an array. I know that in plot.scatter() this can be done with cmap=''. But i can't seem to find the same functionality with plot.bar(). Any advice? is the figure in question.
fig, season = plt.subplots()
# show the phenology season
season.set_ylabel('GPP 20th percent yearly max')
season.tick_params('y', colors = 'blue', labelsize =24)
season.bar(x = pheno['SRO_SoS'], height= pheno['SRO_20th'], width =
pheno['SRO_DateDelta'], zorder=1, color = 'wheat', align =
'edge')
season.set_ylim(0,5)
temp = season.twinx()
temp.plot(df_w.index, df_w['TA_F'],color = 'red', label = 'Tempurature',
linewidth = 2)
# set x-label
temp.set_xlabel('Date')
temp.tick_params('x', labelsize =24)
# set primary y label
temp.set_ylabel('Tempurature (C)')
temp.tick_params('y', colors = 'red', labelsize =24)
# set x-axis limits as the min and max of the series
temp.set_xlim(date2num([df_w.index.min(), df_w.index.max()]))
temp.xaxis.set_major_formatter(mdates.DateFormatter('%d-%m-%Y'))
temp.xaxis.set_major_locator(mdates.YearLocator(1, month=1, day=1))
temp.set_ylim(2,30)
temp.grid(True)
plt.show()
You can give an array to the color argument in your season.bar(). That should work.
If you want to give discrete colors, here is an example.
fig, season = plt.subplots()
clist = ['red', 'blue', 'green']
season.bar(x = range(1, 11), height= range(10, 30, 2), width = 0.8, zorder=1, color = clist, align = 'edge')
Discrete colors - Output plot
For using cmap continuous colors, here is another example.
fig, season = plt.subplots()
my_cmap = plt.get_cmap("viridis")
colorrange = [0,0.25,0.5,0.75,1.0] #Range should be in range of 0 to 1
season.bar(x = range(1, 11), height= range(10, 30, 2), width = 0.8, zorder=1, color=my_cmap(colorrange), align = 'edge')
Continuous colors - Output plot

How to create a variable fontsize for bar plot annotations

How to choose the font size for text annotations inside the bars of the bar graph with the condition:
Text will completely cover the rectangular bar area.
Please go through the diagram and code for better clarity about the problem.
So, the requirement is only : font size should be relative to bars in the bar graphs
Code
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
# Plot styles
mpl.style.use("ggplot")
# data
fruits = pd.Series(index = ["Apples", "Oranges", "Watermelon"], data = [324,518, 258])
# Bar graph for Fruits
# figure
plt.figure(figsize = (7,5))
# bar graph
fruits.plot(kind = "bar", color = ["red", "orange", "green"], alpha = 0.6, width = 0.5, )
# percentage of each fruit type
categories = list(fruits.index)
categories_percent = [100*(value/fruits.sum()) for value in fruits ]
# categories annotations coordinates
ax = plt.gca() # get current axes
rects = ax.patches # rectangles axes of bars in the graph
# annotations
for i in range(len(categories)):
plt.annotate(f"{categories[i]} - {categories_percent[i] : 0.2f}%",
xy = (rects[i].get_x() + rects[i].get_width()/2,
rects[i].get_y() + (ax.get_yticks()[1] - ax.get_yticks()[0])*.2),
fontsize = [20,28,12][i], # Chosen by hit and trial for adjustment
color = "white",
ha = "center",
rotation = 90,
)
plt.ylabel("# Counts", fontsize = 15,)
plt.title("Distribution of Fruits", fontsize = 25, fontname = "Monospace", alpha = .6)
plt.xticks([])
plt.tight_layout(rect=[0, 0, 1, 1])
plt.show()
How to deal with this line of code fontsize = [20,28,12][i], # Chosen by hit and trial for adjustment to adjust the font size dynamically with respect to bar area?
Updating the existing annotation with an adjustable fontsize
From a logical perspective figure sizes' y acts as a scaling factor for height.
Think .get_height as a relative height of the figure.
The actual height is the y scaling factor multiplied with .get_height.
About including breadth, we can include relative breadth which is just .get_width (not get_width*x), however it would just act as a constant, since it's relative width.
We can't include actual width because the font would adjusted unproportionally for y axis.
x,y=15,15
plt.figure(figsize = (x,y))
for i in range(len(categories)):
txt="{} - {: 0.2f} %".format(categories[i],categories_percent[i])
plt.annotate(txt,
xy = (rects[i].get_x() + rects[i].get_width()/2,
rects[i].get_y() + (ax.get_yticks()[1] - ax.get_yticks()[0])*.2),
fontsize = (rects[i].get_height())*y*.2/len(txt), # Chosen by hit and trial for adjustment
color = "white",
ha = "center",
rotation = 90,
)
The entire code can be written more cleanly as follows
# data
fruits = pd.Series(index = ["Apples", "Oranges", "Watermelon"], data=[324,518, 258])
# calculate percent
per = fruits.div(fruits.sum()).mul(100).round(2)
# bar graph
y = 5
ax = fruits.plot(kind="bar", color=["red", "orange", "green"], alpha=0.6, width=0.5, figsize=(7, y), rot=0)
labels = [f'{fruit} - {per[fruit]}%' for fruit in fruits.index]
# annotations:
for label, p in zip(labels, ax.patches):
left, bottom, width, height = p.get_bbox().bounds
fs = height * y * 0.18 / len(label)
ax.annotate(label, xy=(left+width/2, bottom+height/2), ha='center', va='center', rotation=90, fontsize=fs)
plt.ylabel("# Counts", fontsize=15,)
plt.title("Distribution of Fruits", fontsize=25, fontname="Monospace", alpha=.6)
plt.xticks([])
plt.tight_layout(rect=[0, 0, 1, 1])
plt.show()
For figsize=(15,15):
For figsize=(8,8):
For figsize=(7,5):

Issue with plots in Spyder

When I use plt.plot(x,y) I get the following in Spyders plot display by default:
However, I want:
black axes lines and white background. How do I set this?
ax4.axes.get_xaxis().set_visible(True)
ax4.spines['bottom'].set_color('black')
ax4.tick_params(axis='x', colors='black')
ax4.tick_params(axis='y', colors='black')
did not work.
Code to get default:
fig = plt.figure(figsize=(8.5,11))
ax4 = fig.add_subplot(3,1,2)
Dist25 = np.load('Dist25.npy')
Dist100 = np.load('Dist100.npy')
r =1
#
ax4.plot(Dist25[0::r,3],Dist25[0::r,0],'or', color = 'xkcd:azure')
ax4.plot(Dist100[0::r,3],Dist100[0::r,0],'<r', color = 'xkcd:chartreuse')
ax4.set_xscale('log')
ax4.set_ylim((1.5,2.5))
ax4.fill_between(Dist25[0::r,3], Dist25[0::r,0] - Dist25[0::r,1], Dist25[0::r,0] + Dist25[0::r,1],
color='xkcd:azure', alpha=0.2)
ax4.fill_between(Dist100[0::r,3], Dist100[0::r,0] - Dist100[0::r,1], Dist100[0::r,0] + Dist100[0::r,1],
color='xkcd:chartreuse', alpha=0.2)
for tick in ax4.xaxis.get_majorticklabels(): # example for xaxis
tick.set_fontsize(18)
for tick in ax4.yaxis.get_majorticklabels(): # example for xaxis
tick.set_fontsize(18)
ax4.set_title('B) Distance from chain', fontsize = 25)
ax4.set_xlabel('Simulation time (ps)', fontsize = 20)
ax4.set_ylabel('Distance (nm)', fontsize = 20)
I solved this by adding:
plt.style.use('classic')
to my code :)

How can I edit the xticks on a python twinx?

I've got two pandas series I would like to plot on the same axis, using a twinx. Here is a picture of what it looks like:
fig,(ax1,ax2,ax3,ax4,ax5) = plt.subplots(nrows = 5,ncols = 1, figsize = (8,13))
plt.subplots_adjust(hspace = 0.5)
ax1_1 = ax1.twinx()
df[["Var"]].plot(ax = ax1, label = 'Variance')
df[['w2']].plot(ax = ax1_1, color = 'g', label = '$w$')
ax1.locator_params('y',nbins = 5)
ax1_1.locator_params('y', nbins = 5)
ax1.set_ylabel('AC', labelpad = 10)
ax1_1.set_ylabel('w', labelpad = 10)
ax1.legend(loc = 'upper left')
ax1_1.legend()
I'd like to edit the x axis ticks, but using ax1.set_xticks() and ax1.set_xticklabels() doesn't seem to work. Furthermore, why are there are no x ticks after I execute the code found above? Shouldn't the ticks be the index of the Series?

Categories

Resources