Grid is not correct with imshow matrix - python

I am trying to make a confusion matrix plot, or just any plot with quadrants and something in it. I used imshow.
cm = [[370288, 5190],
[ 2213, 6758]]
with plt.style.context("seaborn-white"):
ax = plt.gca()
ax.imshow(cm, interpolation='none', vmin=1, vmax=1)
classNames = ['no churn','churn']
ax.set_title('Confusion Matrix',fontsize=20, fontweight='bold', color='indigo')
ax.set_ylabel('actual',fontsize=15, fontweight='bold')
ax.set_xlabel('predicted',fontsize=15, fontweight='bold')
tick_marks = np.arange(len(classNames))
plt.xticks(tick_marks, classNames)
plt.yticks(tick_marks, classNames, rotation=90)
plt.grid(color='indigo', linestyle='-', linewidth=5)
s = [['TN','FP'], ['FN', 'TP']]
for i in range(2):
for j in range(2):
plt.text(j,i, str(s[i][j])+" = "+annot[i][j], size=12, ha='center', va='center')
plt.show()
Unfortunately I don't manage to make the grid right. If I add
ax.set_xticks(np.arange(-.5, 1.5, 1))
ax.set_yticks(np.arange(-.5, 1.5, 1))
then the grid is correct but the x and y axis labels are not centered anymore and right and left border are not bold. How can I have bold borders and the correct grid that divides the whole plot into four quadrants?

Related

matplotlib: Twinx() hides the minor grid of primary axis

I want to:
A. See two y-axes (of two different graphs) with one x-axis.
B. See major gridlines for x-axis
c. See major and minor gridlines for y-axis of the primary plot
I can plot the graph perfectly with only one y-axis, BUT as soon as I uncomment "ax2 = ax1.twinx()", the minor gridlines of the primary axis disappear.
Picture: The correct format with single plot, and the minor_grid-problem with two plots.
Thank you in advance!
def plot_graph(x, y1, label1, y2, label2, title):
fig, ax1 = plt.subplots()
# Plotting y-axis 1
ax1.set_xlabel('Time (s)')
ax1.set_ylabel(label1, color = "red")
ax1.grid(which='major',axis='both', color='black', linewidth=1)
ax1.grid(which='minor',axis='y', color='gray', linewidth=0.3)
ax1.tick_params(axis = 'y')
ax1.plot(x, y1, color = "red")
# Plotting secondary y-axis with the same x-axis
ax2 = ax1.twinx() # PROBLEM: this alone hides the ax1 minor grid
ax2.set_ylabel(label2, color = 'blue')
ax2.plot(x,y2,color = 'blue')
ax2.tick_params(axis = 'y')
plt.minorticks_on()
plt.legend(loc='best')
plt.title(title)
plt.show()
return
Problem solved.
"plt.minorticks_on()" needs to be called before "ax2 = ax1.twinx()".
"axis='both'" in ax1.grid() does not work. => call separately for x and y axes.
'''
plot_graph(x, y1, label1, y2, label2, title):
fig, ax1 = plt.subplots()
#Plotting y-axis 1
ax1.set_xlabel('Time (s)')
ax1.set_ylabel(label1, color="red")
ax1.grid(which='major',axis='x', color='black', linewidth=1) # x major black
ax1.grid(which='minor',axis='x', color='gray', linewidth=0.3) # x minor gray
ax1.grid(which='major',axis='y', color = 'k', linewidth=1) # y major black
ax1.grid(which='minor',axis='y', color = 'gray',linewidth=0.3) # y minor gray (this was not showing)
ax1.plot(x, y1, color = "red")
plt.minorticks_on() # NEW PLACE - SOLUTION
#Plotting secondary y-axis with the same x-axis
ax2 = ax1.twinx()
ax2.set_ylabel(label2, color = 'blue')
ax2.plot(x,y2,color = 'blue')
ax2.tick_params(axis = 'y')
#plt.minorticks_on() # OLD PLACE
plt.legend(loc='best')
plt.title(title)
plt.show(block=False)
return
'''
Image: Correct output
The problem appears to be because of the axis='both' in the ax.grid lines. If you give it as both, it doesn't appear to like it and I am not sure why. I played around this appears to give what you need. Note that 3 of the grid lines are with ax1 and the other two are with ax2
Note:
I have some random numbers for x, y1, y2
I have given separate colors for X, y1/y2 major/minor lines so you
can see. Use the colors as you need.
Code
x = []
y1 = []
y2 = []
for i in range(0,10):
x.append(round(random.random()*160,2))
for i in range(0,10):
y1.append(round(random.random()*3000,2))
for i in range(0,10):
y2.append(round(random.random()*90,2))
fig, ax1 = plt.subplots()
# Plotting y-axis 1
ax1.set_xlabel('Time (s)')
ax1.set_ylabel('label1', color = "red")
ax1.grid(which='major', axis = 'x', color='g', linewidth=1) #Green Vertical major
ax1.grid(which='major', axis = 'y', color='m', linewidth=1) #Magenta Horizontal major
ax1.grid(which='minor', axis = 'x', color='y', linewidth=0.3) #Yellow Vertical minor
ax1.tick_params(axis = 'y')
ax1.plot(x, y1, color = "red")
# Plotting secondary y-axis with the same x-axis
ax2 = ax1.twinx() # PROBLEM STILL?
ax2.set_ylabel('label2', color = 'blue')
ax2.plot(x,y2,color = 'blue')
ax2.tick_params(axis = 'y')
ax2.grid(which='major', axis = 'y', color='k', linewidth=1) #Black Horizontal major
ax2.grid(which='minor', axis = 'y', color='grey', linewidth=0.3) #Grey Horizontal minor
plt.minorticks_on()
plt.legend(loc='best')
plt.title('title')
plt.show()
Graph

change prophet scatter plot colors

hello im ussing fb prophet and changing old white layout for a better experience, i manage to change background and line colors in 'plot.py' , but cant change black scatters as seen on pic.
allready make a search but dont find a way
how can i change it?
if ax is None:
fig = plt.figure(facecolor='w', figsize=figsize)
ax = fig.add_subplot(111)
else:
fig = ax.get_figure()
fcst_t = fcst['ds'].dt.to_pydatetime()
ax.plot(m.history['ds'].dt.to_pydatetime(), m.history['y'], 'k.')
ax.plot(fcst_t, fcst['yhat'], ls='-', c='#0072B2')
if 'cap' in fcst and plot_cap:
ax.plot(fcst_t, fcst['cap'], ls='--', c='k')
if m.logistic_floor and 'floor' in fcst and plot_cap:
ax.plot(fcst_t, fcst['floor'], ls='--', c='k')
if uncertainty and m.uncertainty_samples:
ax.fill_between(fcst_t, fcst['yhat_lower'], fcst['yhat_upper'],
color='#ffffff', alpha=0.2)
# Specify formatting to workaround matplotlib issue #12925
locator = AutoDateLocator(interval_multiples=False)
formatter = AutoDateFormatter(locator)
ax.xaxis.set_major_locator(locator)
ax.xaxis.set_major_formatter(formatter)
ax.grid(True, which='major', c='white', ls='-', lw=1, alpha=0.2)
ax.set_xlabel(xlabel)
ax.set_ylabel(ylabel)
fig.tight_layout()
return fig
my plot

How Can I space legend items with variable spacing and have legend marker colors reflect the colormap

I would like to have an increasing spacing between legend items instead of a single value (labelspacing). The latter only accepts an int value type, but I want a variable spacing between legend items. Also, I want the markerfacecolor to follow the colormap used when creating the scatter plot.
N = 45
x, y = np.random.rand(2, N)
s = np.random.randint(10, 1000, size=N)
fig, ax = plt.subplots()
scatter = ax.scatter(x, y, c=s, s=s)
cbar = fig.colorbar(scatter,
ax=ax,
label='Size',
fraction=0.1,
pad=0.04)
# produce a legend with a cross section of sizes from the scatter
handles, labels = scatter.legend_elements(prop="sizes", alpha=0.6)
for hd in handles:
hd.set_markeredgewidth(2)
hd.set_markeredgecolor("red")
hd.set_markerfacecolor('blue')
legend2 = ax.legend(
handles[::2], labels[::2], loc="upper right", title="Sizes", labelspacing=1.2
)
plt.show()
I searched StackOverflow and tried some possible methods but without success. Could someone guide how I can achieve the desired output?
I managed to set markerfacecolor as the colormap. But I am still struggling with the variable labelspacing!.
Any help!
N = 45
x, y = np.random.rand(2, N)
s = np.random.randint(10, 1000, size=N)
fig, ax = plt.subplots()
scatter = ax.scatter(x, y, c=s, s=s)
cbar = fig.colorbar(scatter,
ax=ax,
label='Size',
fraction=0.1,
pad=0.04)
# produce a legend with a cross section of sizes from the scatter
handles, labels = scatter.legend_elements(prop="sizes", alpha=0.6)
leg_colrs = [color.get_markerfacecolor() for color in scatter.legend_elements()[0]]
for hd, color in zip(handles, leg_colrs):
hd.set_markeredgewidth(2)
hd.set_markeredgecolor("red")
hd.set_markerfacecolor(color)
legend2 = ax.legend(
handles[::2], labels[::2], loc="upper right", title="Sizes", labelspacing=1.2
)
plt.show()

matplotlib: horizontal spacing of subplots with equal aspect ratio

I'm trying to draw two rows with three columns of pcolormesh plots and a combined colorbar for all plots. So far it seems to work. However, I'm sure I'm not using the most elegant way...
The only problem I have, is that I can't decrease the horizontal spacing any further. The following line should set the horizontal spacing to zero:
fig.subplots_adjust(left=0.05, right=0.98, top=0.93, bottom=0.00, wspace=0, hspace=0.03)
But this does not work in conjunction with
ax.set_aspect('equal')
I've attached a small code snippet that creates the following figure:
Example figure
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
rows = 2
columns = 3
fig = plt.figure()
gs = gridspec.GridSpec(rows+1, columns)
lines = []
x = np.linspace(1,10,100)
y = x
X, Y = np.meshgrid(x,y)
Z = np.random.rand(100,100)
lines = []
for i in range(rows):
lines.append([])
for j in range(columns):
ax = fig.add_subplot(gs[i, j])
line = ax.pcolormesh(X, Y, Z, cmap=plt.cm.Reds)
lines[i].append(line)
ax.set_aspect('equal')
for tick in ax.get_xticklabels():
tick.set_rotation(45)
if i!=rows-1:
ax.set_xticklabels([])
if j!=0:
ax.set_yticklabels([])
#title
props = dict(boxstyle='round', facecolor='white', alpha=0.7)
ax.text(0.05, 0.95, "plot (%i, %i)" % (i,j), transform=ax.transAxes, fontsize=5,
verticalalignment='top', bbox=props)
ax.tick_params(labelsize=7)
cb_ax = fig.add_subplot(gs[-1,:])
cb_ax.set_aspect(0.05)
cbar = fig.colorbar(lines[0][0], cax=cb_ax, orientation='horizontal')
cb_ax.tick_params(labelsize=7)
fig.subplots_adjust(left=0.05, right=0.98, top=0.93, bottom=0.00, wspace=0, hspace=0.03)
#fig.tight_layout()
fig.text(0.5, 0.2, "x axis", ha='center', va='center')
fig.text(0.5, 0.97, "overall title", ha='center', va='center')
fig.text(0.02, 0.5, "y axis", ha='center', va='center', rotation='vertical')
fig.text(0.5, 0.02, "quantity [unit]", ha='center', va='center',)
plt.savefig("test.png", dpi=600)

Customizing Subplot Orientation and Size with Maplotlib

I am trying to plot 5 subplots in Python with differing sizes and orientation. I have seen usage of gridspec to alter column width, plt.figure(figsize=[]), etc. but each seems to be slightly off from what I want (e.g. no uniform column width, all one plot, so can't use plt.figure()).
What I currently have is a subplot(3,2,2) with the first 5 plots filled such that it looks like a 3x2 grid without the bottom right filled in. What I would like is a 2x2 grid with a single plot below it. The plot below should also be larger (maybe twice as wide) as the four above it.
This is what I have versus what I would like.
Here is my code (sorry for the line numbers):
plot3 = plt.figure(1)
plt.subplot(321)
#gs = gridspec.GridSpec(1,2,3,4,5,6,width_ratios=[1,1,1,1,2,0])
plt.scatter(0.001*posEncUm[:,0],err[:,0], s=1, linewidths=1)
p = np.polyfit(0.001*posEncUm[:,0],err[:,0],1)
plt.title('Slope = {0:4.1f} um/100mm'.format(p[0]*100), fontsize=10)
plt.xlabel('Encoder Position (X), mm', fontsize=7)
plt.ylabel('Laser Error (X), um', fontsize=7)
plt.subplots_adjust(hspace = 1.0, wspace = 0.5)
plt.grid()
plt.subplot(322)
plt.scatter(0.001*posEncUm[:,1],err[:,0], s=1, linewidths=1)
p = np.polyfit(0.001*posEncUm[:,1],err[:,0],1)
plt.title('Slope = {0:4.1f} um/100mm'.format(p[0]*100), fontsize=10)
plt.xlabel('Encoder Position (Y), mm', fontsize=7)
plt.ylabel('Laser Error (X), um', fontsize=7)
plt.grid()
plt.subplot(323)
plt.scatter(0.001*posEncUm[:,0],err[:,1], s=1, linewidths=1)
p = np.polyfit(0.001*posEncUm[:,0],err[:,1],1)
plt.title('Slope = {0:4.1f} um/100mm'.format(p[0]*100), fontsize=10)
plt.xlabel('Encoder Position (X), mm', fontsize=7)
plt.ylabel('Laser Error (Y), um', fontsize=7)
plt.grid()
plt.subplot(324)
plt.scatter(0.001*posEncUm[:,1],err[:,1], s=1, linewidths=1)
p = np.polyfit(0.001*posEncUm[:,1],err[:,1],1)
plt.title('Slope = {0:4.1f} um/100mm'.format(p[0]*100), fontsize=10)
plt.xlabel('Encoder Position (Y), mm', fontsize=7)
plt.ylabel('Laser Error (Y), um', fontsize=7)
plt.grid()
plt.subplot(325)
plt.quiver(0.001*X,0.001*Y,errX,errY)
plt.grid()
plt.xlabel('Encoder Pos (X), mm')
plt.ylabel('Encoder Pos (Y), mm')
plt.gca().set_aspect('equal', adjustable = 'box')
This will give what you want, just modify for the specifics. Is this what you were thinking?
import pylab as pl
fig = pl.figure(figsize=(3.25, 4.5))
gs = pl.GridSpec(3, 2)
gs.update(left=0.08, right=0.925,
top=0.95, bottom=0.05,
hspace=0.3, wspace=0.1)
# create primary axes
ax0 = pl.subplot(gs[0, 0])
ax1 = pl.subplot(gs[0, 1])
ax2 = pl.subplot(gs[1, 0])
ax3 = pl.subplot(gs[1, 1])
ax4 = pl.subplot(gs[2, :])
I don't know what you mean by "bottom should be twice as wide as four above it."
#https://python-graph-gallery.com/125-small-multiples-for-line-chart/
import matplotlib.gridspec as gridspec
import matplotlib.pyplot as plt
# Initialize the figure
plt.style.use('seaborn-darkgrid')
# create a color palette
palette = plt.get_cmap('Set1')
plt.figure(figsize=(10,10))
plt.suptitle("PLOT TITLE",fontsize=20)
gridspec.GridSpec(3,3)
plt.subplots_adjust(hspace=0.4)
# multiple line plot
num=0
for column in df.drop('ODD COLUMN NAME', axis=1):
num+=1
# Find the right spot on the plot
if num==7: # adjustment to fit ODD COLUMN
plt.subplot2grid((3,3),(2,0),colspan=3)
else:
plt.subplot(3,3, num)
# plot every groups, but discreet
for v in df.drop('ODD COLUMN', axis=1):
plt.plot(df['ODD COLUMN'], df[v], marker='', color='grey', linewidth=0.6, alpha=0.3)
# Plot the lineplot
plt.plot(df['ODD COLUMN'], df[column], marker='', color=palette(num), linewidth=2.4, alpha=0.9, label=column)
# Same limits for everybody!
plt.xlim(10,100)
plt.ylim(1,100)
# Not ticks everywhere
if num in range(4) :
plt.tick_params(labelbottom='off')
if num not in [1,4,7] :
plt.tick_params(labelleft='off')
# Add title
plt.title(column, loc='left', fontsize=12, fontweight=0, color=palette(num))

Categories

Resources