Seaborn kdeplot change title - matplotlib

I have the following code:
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
sns.set_style("darkgrid")
s1, s2 = 5, 3
fig, axes = plt.subplots(s1, s2, figsize=(4*5, 5*5), sharey=True)
fig.suptitle(t="Suptitle", x=0.5, y=1-0.075, fontsize=40)
for ind1 in range(s1):
for ind2 in range(s2):
data=np.random.normal(size=100)
sns.kdeplot(data, ax=axes[ind1, ind2], bw_adjust=1,
linewidth=0.9, color="C9", alpha=0.5)
for ax, col in zip(axes[0], ["column_%d" %i for i in range(s2)]):
ax.set_title(col, size=25)
for ax, row in zip(axes[:,-1], ["row_%d" %i for i in range(s1)]):
ax.yaxis.set_label_position("right")
ax.set_ylabel(row, rotation=90, size=25)
fig.text(0.5, 0.075, 'Common x label', ha='center', size = 30)
fig.text(0.065, 0.5, 'Common y label', va='center', rotation='vertical', size = 30)
fig.show()
I expect to see Something like this: .
Bur really seaborn.kdeplot breaks my picture: it changes y label and writes the word "Density" on the left hand instead of uses my own title (row0, ..., row3) on the right hand:
How can I fix it?
Thank you in advance

You can't set the ylabel to the right because you are using subplot with shared y.
To get the plot you want, you can set the ylabels to be blank, and add the ylabel as text on the defined subplots:
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
sns.set_style("darkgrid")
s1, s2 = 5, 3
fig, axes = plt.subplots(s1, s2, figsize=(4*5, 5*5), sharey=True)
fig.suptitle(t="Suptitle", x=0.5, y=1-0.075, fontsize=40)
for ind1 in range(s1):
for ind2 in range(s2):
data=np.random.normal(size=100)
sns.kdeplot(data, ax=axes[ind1, ind2], bw_adjust=1,
linewidth=0.9, color="C9", alpha=0.5)
axes[ind1, ind2].set_ylabel("")
for ax, col in zip(axes[0], ["column_%d" %i for i in range(s2)]):
ax.set_title(col, size=25)
for ax, row in zip(axes[:,-1], ["row_%d" %i for i in range(s1)]):
ax.text(1, 0.5, row, horizontalalignment='left',
verticalalignment='center',rotation = 'vertical',
size = 25,transform=ax.transAxes)
fig.text(0.5, 0.075, 'Common x label', ha='center', size = 30)
fig.text(0.065, 0.5, 'Common y label', va='center', rotation='vertical', size = 30)
fig.show()

Related

how could I make my data label in chart become percentage format?

I want to draw a line & bar chart by matplotlib.my code is like this, you can see data label's format is number in my chart:
import matplotlib.pyplot as plt
from matplotlib import ticker
import numpy as np
plt.rcParams['font.sans-serif'] = ['Arial Unicode MS']
plt.figure(figsize=(9, 6), dpi=100)
x = ['>12 Months','6-12 Months','3-6 Months','1-3 Months','1-4 Weeks','>1 Times Per Week']
y = [0.0964,0.1607,0.4158,0.3054,0.0215,0.0001]
z = [11544,19247,49794,36572,2578,16]
plt.bar(x=x, height=z, label='Vehicles Num', color='Blue', alpha=0.7, width=0.5)
plt.legend(loc="upper left")
plt.title("Frequency Distribution of Hood Ajar/Closed Events",size=15)
plt.xlabel("Frequency",size=13)
plt.ylabel("Number of Vehicles",size=13)
ax2 = plt.twinx()
ax2.set_ylabel("Percentage",size=13)
ax2.plot(y)
ax2.yaxis.set_major_formatter(ticker.PercentFormatter(xmax=1, decimals=1))
plt.plot(x, y, "r", marker='.', c='r', ms=8, linewidth='1', label="Percentage")
plt.legend(loc="upper right")
for a, b in zip(x, y):
plt.text(a, b, b, ha='center',va='bottom',fontsize=13)
plt.show()
The result I want:
the data label list "y", can show like:9.64%, 16.07%
Many Thanks~
You can use below code i have changes may help!!(Mark use full if helps!!!)
import matplotlib.pyplot as plt
from matplotlib import ticker
import numpy as np
plt.rcParams['font.sans-serif'] = ['Arial Unicode MS']
plt.figure(figsize=(9, 6), dpi=100)
x = ['>12 Months','6-12 Months','3-6 Months','1-3 Months','1-4 Weeks','>1 Times
Per Week']
y = [0.0964,0.1607,0.4158,0.3054,0.0215,0.0001]
y=np.multiply(y,100)
z = [11544,19247,49794,36572,2578,16]
plt.bar(x=x, height=z, label='Vehicles Num', color='Blue', alpha=0.7, width=0.5)
plt.legend(loc="upper left")
plt.title("Frequency Distribution of Hood Ajar/Closed Events",size=15)
plt.xlabel("Frequency",size=13)
plt.ylabel("Number of Vehicles",size=13)
ax2 = plt.twinx()
ax2.set_ylabel("Percentage",size=13)
ax2.plot(y)
ax2.yaxis.set_major_formatter(ticker.PercentFormatter(xmax=1, decimals=1))
plt.plot(x,y, "r", marker='.', c='r', ms=8, linewidth='1', label="Percentage")
plt.legend(loc="upper right")
for a, b in zip(x, y):
plt.text(a, b,str(b) +'%', ha='center',va='bottom',fontsize=13)
plt.show()

Is there a way to plot pie chart in matplotlib heatmap?

I have a heatmap with several rows and columns.
Formerly, I was plotting a circle for each (row_index,column_index) and appending this circle to a circle_list. I was adding circle_list as a collection to the axes.
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.collections import PatchCollection
def heatmap_with_circles(data_array,row_labels,column_labels,ax=None, cmap=None, norm=None, cbar_kw={}, cbarlabel="", **kwargs):
circles=[]
for row_index, row in enumerate(row_labels):
for column_index, column in enumerate(column_labels):
circles.append(plt.Circle((row_index,column_index),radius=0.4))
col = PatchCollection(circles, array=data_array.flatten(), cmap=cmap, norm=norm)
ax.add_collection(col)
# We want to show all ticks...
ax.set_xticks(np.arange(data_array.shape[1]))
ax.set_yticks(np.arange(data_array.shape[0]))
fontsize=10
ax.set_xticklabels(column_labels, fontsize=fontsize)
ax.set_yticklabels(row_labels, fontsize=fontsize)
#X axis labels at top
ax.tick_params(top=True, bottom=False,labeltop=True, labelbottom=False,pad=5)
plt.setp(ax.get_xticklabels(), rotation=55, ha="left", rotation_mode="anchor")
# We want to show all ticks...
ax.set_xticks(np.arange(data_array.shape[1]+1)-.5, minor=True)
ax.set_yticks(np.arange(data_array.shape[0]+1)-.5, minor=True)
ax.grid(which="minor", color="black", linestyle='-', linewidth=3)
ax.tick_params(which="minor", bottom=False, left=False)
data_array=np.random.rand(3,4)
row_labels=['Row1', 'Row2', 'Row3']
column_labels=['Column1', 'Column2', 'Column3','Column4']
fig, ax = plt.subplots(figsize=(1.9*len(row_labels),1.2*len(column_labels)))
ax.set_aspect(1.0)
ax.set_facecolor('white')
heatmap_with_circles(data_array,row_labels,column_labels, ax=ax)
plt.tight_layout()
plt.show()
However, now I need to plot a pie chart instead of a circle.
And pie chart does not have (row_index,column_index) parameters.
Is there a way to plot pie chart in each cell of matplotlib heatmap?
Updating the for loop in heatmap_with_circles as follows:
for row_index, row in enumerate(row_labels,0):
for column_index, column in enumerate(column_labels,0):
wedges, _ = plt.pie([20, 10, 5])
radius = 0.45
[w.set_center((column_index,row_index)) for w in wedges]
[w.set_radius(radius) for w in wedges]
results in
You can access each wedge created by plt.pie individually and then use set_radius and set_position to rescale the different wedges.
wedges, _ = plt.pie([1,2,3])
x_position, y_position = 0, 0
radius = 0.2
[w.set_center((x_position,y_position)) for w in wedges]
[w.set_radius(radius) for w in wedges]
Edit:
On your code, in the for loop
for row_index, row in enumerate(row_labels):
for column_index, column in enumerate(column_labels):
wedges, _ = plt.pie([1,2,3])
[w.set_center((row_index,column_index)) for w in wedges]
[w.set_radius(0.4) for w in wedges]

How to show ranges of values with a color assigned in the legend?

With this code i'm creating colorbar scales with the function make_colormap. Source:Create own colormap using matplotlib and plot color scale
import matplotlib.colors as mcolors
def make_colormap(seq):
"""Return a LinearSegmentedColormap
seq: a sequence of floats and RGB-tuples. The floats should be increasing
and in the interval (0,1).
"""
seq = [(None,) * 3, 0.0] + list(seq) + [1.0, (None,) * 3]
cdict = {'red': [], 'green': [], 'blue': []}
for i, item in enumerate(seq):
if isinstance(item, float):
r1, g1, b1 = seq[i - 1]
r2, g2, b2 = seq[i + 1]
cdict['red'].append([item, r1, r2])
cdict['green'].append([item, g1, g2])
cdict['blue'].append([item, b1, b2])
return mcolors.LinearSegmentedColormap('CustomMap', cdict)
c = mcolors.ColorConverter().to_rgb
rvb = make_colormap([c('grey'), c('grey'), norm(3), c('sandybrown'), c('sandybrown'),
norm(5), c('yellow'), c('yellow'), norm(10), c('navajowhite'),
c('navajowhite'), norm(15),c('lightgreen'), c('lightgreen'),norm(20),c('lime'), c('lime'),
norm(50),c('limegreen'), c('limegreen'),norm(80),c('forestgreen'), c('forestgreen'),norm(120),
c('green'), c('green'),norm(160),c('darkgreen'), c('darkgreen'),norm(200),c('teal'), c('teal'),norm(300),
c('mediumaquamarine'), c('mediumaquamarine'),norm(500),c('lightseagreen'), c('lightseagreen'),norm(700),
c('lightskyblue'), c('lightskyblue')])
So in variable rvb i'm asssing a color to ranges of values. How can i assing a color to an specific ranges of values? For example: Grey to 0-3, sandybrown to 4-5, yellow to 6-10, etc.
The map is this:
Also i want to the legend show those values assigned. For example Grey color 0-3, sandybrown 4-5, etc.
Something similar to this image (no need to be equal to the image, just need to show ranges with colors):
I also will show you part of my code when i create the map:
fig = plt.figure('map', figsize=(7,7), dpi=200)
ax = fig.add_axes([0.1, 0.12, 0.80, 0.75], projection=ccrs.PlateCarree())
plt.title('xxx')
plt.xlabel('LONGITUD')
plt.ylabel('LATITUD')
ax.outline_patch.set_linewidth(0.3)
l = NaturalEarthFeature(category='cultural', name='admin_0_countries', scale='50m', facecolor='none')
ax.add_feature(l, edgecolor='black', linewidth=0.25)
img = ax.scatter(lons, lats, s=7, c=ppvalues, cmap=rvb,norm=norm,
marker='o', transform=ccrs.PlateCarree())
handles, labels = img.legend_elements(alpha=0.2)
plt.legend(handles, labels,prop={'weight':'bold','size':10}, title='Meteorological\nStations',title_fontsize=9, scatterpoints=2);
cb = plt.colorbar(img, extend='both',
spacing='proportional', orientation='horizontal',
cax=fig.add_axes([0.12, 0.12, 0.76, 0.02]))
ax.set_extent([-90.0, -60.0, -20.0, 0.0], crs=ccrs.PlateCarree())
I don't understand the function in the question, but I have coded how to create a legend with a specified color, specified label, and specified ticks, and how to give a color bar a specified tick. Please correct the addition of colors and the tick spacing in the color bar.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
from matplotlib.colors import LinearSegmentedColormap
list_color = ['grey','sandybrown','sandybrown','yellow',
'navajowhite','lightgreen','lime','limegreen',
'forestgreen','green','darkgreen','teal',
'mediumaquamarine','lightseagreen','lightskyblue']
list_label = ['0-3', '4-5', '6-10', '11-15',
'16-20', '21-50', '51-80', '81-120',
'121-160', '161-200','201-300','301-500',
'501-700','701-900','901-1200']
list_ticks = np.linspace(0, 1, 15)
vmin,vmax = 0, 1
cm = LinearSegmentedColormap.from_list('custom_cmap', list_color, N=len(list_color))
plt.imshow(np.linspace(0, 1, 25).reshape(5,5), cmap=cm, interpolation='nearest', vmin=vmin, vmax=vmax)
cbar = plt.colorbar( orientation='horizontal', extend='neither', ticks=list_ticks)
cbar.ax.set_xticklabels(list_label, rotation=45, fontsize=14)
all_patches = []
for h,l in zip(list_color, list_label):
patch = mpatches.Patch(color=h, label=l)
all_patches.append(patch)
plt.legend(handles=all_patches, loc='upper right', ncol=3, bbox_to_anchor=(3, 1))
plt.show()

Matpliblib colormap with peak at center and zero at edges

I am looking for a custom colormap that highlights the center (value of 1) and just has white color at the edges (values of 0 and 2). Ideally there should be a gradient from 1 to [0, 2].
Usual colormaps do the opposite: diverges from center (white at center).
Thanks for your help
You can use the from_list method from LinearSegmentedColormap for this from the matplotlib.colors module.
Here, we give 3 colors as a list (["white", "red", "white"]). This can easily be customised by changing any of those color names.
For example:
import matplotlib.pyplot as plt
from matplotlib.colors import LinearSegmentedColormap
import numpy as np
cmap = LinearSegmentedColormap.from_list('wrw', ["white", "red", "white"], N=256)
a = np.arange(0, 2, 0.01).reshape(20, 10)
fig, ax = plt.subplots()
p = ax.pcolormesh(a, cmap=cmap, vmin=0, vmax=2)
fig.colorbar(p)
plt.show()
You can create based on availbale colormaps from matplotlib.
from matplotlib.colors import ListedColormap
def show_cmap(ax, cmap):
n = 256
ax.imshow(np.tile(np.arange(n), [int(n*0.20),1]),
cmap=cmap,
interpolation="nearest", aspect="auto")
ax.set_xticks([])
ax.set_yticks([])
ax.set_xticklabels([])
ax.set_yticklabels([])
c1 = plt.cm.Blues(range(0, 128))
c2 = c1[::-1]
c = np.vstack([c1, c2])
cmap = ListedColormap(c)
fig, ax = plt.subplots(1, 1, figsize=(7.2, 7.2))
show_cmap(ax, cmap)

Matplotlib Interpolate empty pixels

I have a file 'mydata.tmp' which contains 3 colums like this:
3.81107 0.624698 0.000331622
3.86505 0.624698 0.000131237
3.91903 0.624698 5.15136e-05
3.97301 0.624698 1.93627e-05
1.32802 0.874721 1.59245
1.382 0.874721 1.542
1.43598 0.874721 1.572
1.48996 0.874721 4.27933
etc.
Then I want to make a heatmap color plot where the first two columns are coordinates, and the third column are the values of that coordinates.
Also, I would like to set the third column in log scale.
I have done this
import pandas as pd
import matplotlib.pyplot as plt
import scipy.interpolate
import numpy as np
import matplotlib.colors as colors
# import data
df = pd.read_csv('mydata.tmp', delim_whitespace=True,
comment='#',header=None,
names=['1','2','3'])
x = df['1']
y = df['2']
z = df['3']
spacing = 500
xi, yi = np.linspace(x.min(), x.max(), spacing), np.linspace(y.min(),
y.max(), spacing)
XI, YI = np.meshgrid(xi, yi)
rbf = scipy.interpolate.Rbf(x, y, z, function='linear')
ZI = rbf(XI, YI)
fig, ax = plt.subplots()
sc = ax.imshow(ZI, vmin=z.min(), vmax=z.max(), origin='lower',
extent=[x.min(), x.max(), y.min(),
y.max()], cmap="GnBu", norm=colors.LogNorm(vmin=ZI.min(),
vmax=ZI.max()))
fig.colorbar(sc, ax=ax, fraction=0.05, pad=0.01)
plt.show()
And I get this Image
which has all these empty pixels.
I am looking for something like this instead (I have done this other picture with GNUplot):
How can I do it?
You could use cmap.set_bad to define a color for the NaN values:
import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import griddata
import matplotlib.colors as colors
from matplotlib import cm
import copy
# Some data
x = np.array([0, 1, 3, 0, 2, 4])
y = np.array([0, 0, 0, 1, 1, 1])
z = np.array([2, 2, 3, 2, 3, 4])
# Interpolation on a grid:
nrb_points = 101
xi = np.linspace(-.5, 4.5, nrb_points)
yi = np.linspace(-.5, 1.5, nrb_points)
XI, YI = np.meshgrid(xi, yi)
xy = np.vstack((x, y)).T
XY = (XI.ravel(), YI.ravel())
ZI = griddata(points, z, XY,
method='linear',
fill_value=np.nan) # Value used [for] points
# outside of the convex hull
# of the input points.
ZI = ZI.reshape(XI.shape)
# Color map:
cmap = copy.copy(cm.jet)
cmap.set_bad('grey', 1.)
# Graph:
plt.pcolormesh(xi, yi, ZI,
#norm=colors.LogNorm(),
cmap=cmap);
plt.colorbar(label='z');
plt.plot(x, y, 'ko');
plt.xlabel('x'); plt.ylabel('y');
the result is:
I would also use griddata instead of RBF method for the interpolation. Then, point outside the input data area (i.e. the convex hull) can be set to NaN.