Density map and ridge map drawing basics

Seaborn's kdeplot() function is one of the ways to draw density maps in Python. Matplotlib does not have a specific function for drawing density maps at this stage. It is usually drawn by combining the function gaussian_kde()results in the Scipy library.

The module in Python's scikit-learn library neighbors.KernelDensity ()provides six kernel functions: Gaussian, Tophat, Epanechnikov, Exponential, Linear and Cosine for kernel density estimation calculations. Python's KDEpy library provides up to 9 kernel functions, including Gaussian, Exponential, Box, Tri, Epa, Biweight, Triweight, Tricube, and Cosine
.

The schematic diagram of the 9 kernel functions in the KDEpy library is as follows:

Comparison of 3 methods for drawing density maps

The following uses the function in Seabornkdeplot () , the function in the Scipy library , and the calculation results of the KDEpy library combined with the function gaussian_kde () in Matplotlib axes.Axes.Plot()to draw the density map respectively.axes.Axes.Fill ()

import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
plt.rcParams["font.family"] = "Times New Roman"
plt.rcParams["xtick.minor.visible"] = True
plt.rcParams["ytick.minor.visible"] = True
plt.rcParams["xtick.direction"] = "in"
plt.rcParams["ytick.direction"] = "in"
plt.rcParams["xtick.labelsize"] = 12
plt.rcParams["ytick.labelsize"] = 12

#构建数据集
data_01 = [5.1,5.2,5.3,5.4,5.5,6.0,6.2,6.3,6.4,6.5,
           7.0,7.5,8.0,8.5,8.8,8.9,9.0,9.5,10,11,
           11.5,12,13,14,14.5,15,15.5,16,16.5,17]

data_02 = [5.1,5.2,5.3,5.4,5.5,6.0,7.0,7.3,7.4,7.5,
           8.0,8.2,8.4,8.6,8.8,9.0,9.2,9.4,9.6,9.8,
           10,10.2,11,11.5,12,12.5,13,13.5,15,16]
data_03 = [5.1,5.2,5.3,5.4,5.6,6.0,6.1,6.2,6.4,6.8,
           7.1,8.2,8.8,9.0,9.2,10.2,10.4,10.8,11,11.6,
           12,12.4,12.6,12.8,13,13.2,13.4,13.6,13.7,13.8]

data_04 = [5.0,5.2,5.3,5.4,5.6,5.8,6.0,6.2,6.4,6.6,
             6.8,7.0,7.2,7.4,7.6,8.0,9.0,9.2,9.6,9.8,
             10,10.3,11,12,16,16,18,18.5,19,22]
data_df = pd.DataFrame({
    
    "data_01":data_01,"data_02":data_02,
                        "data_03":data_03,"data_04":data_04})
                        
                        
#(a) kdeplot()函数绘制密度图示例                                             
fig,ax = plt.subplots(figsize=(4,3.5),dpi=100,facecolor="w")
kde_01 = sns.Kdeplot (x="data_01", data=data_df, color=" #1180D5 ", alpha=1, shade=True, ax=ax)
Sns.Rugplot (data=data_df, x="data_01", color='k', height=. 05, ax=ax)
Ax. Set_xlabel ("Values")
Ax. Set_ylabel ("Density")

Plt.Show ()

#(b) gaussian_kde ()函数绘制密度图示例
From scipy import stats
Density = stats. Kde. Gaussian_kde (data_01)
X = np.Linspace (-2,25,500)
Y = density (x)

Fig, ax = plt.Subplots (figsize=(4,3.5), dpi=100, facecolor="w")
Ax.Plot (x, y, lw=1, color="k")
ax.Fill (x, y, color=" #07A6C5 ")
# 添加单独数据
Ax.Plot (data_01, [0.005]*len (data_01), '|', color='k', lw=1)
Ax. Set_xlabel ("Values")
Ax. Set_ylabel ("Density") 
Plt.Show ()
            
#(c) KDEpy 库计算结果结合 axes.Axes.Plot ()、axes.Axes.Fill ()函数绘制密度图示例
From KDEpy import FFTKDE
X, y = FFTKDE (kernel="gaussian", bw=2). Fit (data_01). Evaluate ()

Fig, ax = plt.Subplots (figsize=(4,3.5), dpi=100, facecolor="w")
Ax.Plot (x, y, lw=1, color="k",)
ax.Fill (x, y, color=" #FBCD2D ")
# 添加单独数据、
Ax.Plot (data_01, [0.005]*len (data_01), '|', color='k', lw=1)
Ax. Set_xlabel ("Values")
Ax. Set_ylabel ("Density") 
Plt.Show ()

It is relatively simple to use the function in Seaborn kdeplot ()to draw density plots. Combined with rugplot ()the function, you can draw the data distribution along the X-axis. The other two methods are kdeplot ()more cumbersome than functions, but they produce clearer density plots.

Note that the kernel density estimation results here are all obtained through the Gaussian kernel function.

Multiple sets of data, the same kernel function

For multiple sets of sample data with different numerical distributions, we often use the same kernel function to fit it and plot the results into density plots. This situation generally occurs during the data exploration phase. The above methods are often used to view the distribution of data in each dimension or to compare differences between different data .

The kernel density plots of multiple sets of sample data drawn by Matplotlib below use the same kernel function, showing the distribution of different data.

import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
plt.rcParams["font.family"] = "Times New Roman"
plt.rcParams["xtick.minor.visible"] = True
plt.rcParams["ytick.minor.visible"] = True
plt.rcParams["xtick.direction"] = "in"
plt.rcParams["ytick.direction"] = "in"
plt.rcParams["xtick.labelsize"] = 12
plt.rcParams["ytick.labelsize"] = 12

#构建数据集
data_01 = [5.1,5.2,5.3,5.4,5.5,6.0,6.2,6.3,6.4,6.5,
           7.0,7.5,8.0,8.5,8.8,8.9,9.0,9.5,10,11,
           11.5,12,13,14,14.5,15,15.5,16,16.5,17]

data_02 = [5.1,5.2,5.3,5.4,5.5,6.0,7.0,7.3,7.4,7.5,
           8.0,8.2,8.4,8.6,8.8,9.0,9.2,9.4,9.6,9.8,
           10,10.2,11,11.5,12,12.5,13,13.5,15,16]
data_03 = [5.1,5.2,5.3,5.4,5.6,6.0,6.1,6.2,6.4,6.8,
           7.1,8.2,8.8,9.0,9.2,10.2,10.4,10.8,11,11.6,
           12,12.4,12.6,12.8,13,13.2,13.4,13.6,13.7,13.8]

data_04 = [5.0,5.2,5.3,5.4,5.6,5.8,6.0,6.2,6.4,6.6,
             6.8,7.0,7.2,7.4,7.6,8.0,9.0,9.2,9.6,9.8,
             10,10.3,11,12,16,16,18,18.5,19,22]
data_df = pd.DataFrame({
    
    "data_01":data_01,"data_02":data_02,
                        "data_03":data_03,"data_04":data_04})
                        
                        

nrow = 2
ncol = 2
ax_label = ["a.","b.","c.","d."]
titles = ["Type One","Type Two","Type Three","Type Four"]
indexs = [i for i in data_df.columns] 

fig,axs = plt.subplots(nrow,ncol,figsize=(5,4),dpi=100,facecolor="w",sharey=True,sharex=True,
                      constrained_layout=True)
for ax, index,label in zip(axs.flat, indexs,ax_label):
    x,y = NaiveKDE(kernel="Gaussian",bw=2).fit(data_df[index].values).evaluate()
    ax.plot(x,y, lw=1,color="#1BB71B")
    ax.fill(x,y,color="#1BB71B",alpha=.6)
    # 添加单独数据、
    ax.plot(data_df[index].values, [0.005]*len(data_df[index].values), '|', color='k',lw=1)
    ax.text(0.05, 0.95, label, transform=ax.transAxes,fontsize=16, fontweight='bold', va='top')
    ax.text(0.65, 0.95, index,transform=ax.transAxes,fontsize=14, fontweight='bold', va='top')
fig.supxlabel('Values')
fig.supylabel('Density')
plt.show()                    

The operation of using different kernel functions to calculate and draw kernel density map results for the same set of sample data is more inclined to study different kernel functions , and the content involved is very simple.

The figure below shows the results of kernel density plots drawn using different kernel functions for the same set of data.

import numpy as np
import pandas as pd
import seaborn as sns
import proplot as pplt
from KDEpy import NaiveKDE
import matplotlib.pyplot as plt
from proplot import rc

rc["axes.labelsize"] = 15
rc['tick.labelsize'] = 12
rc["suptitle.size"] = 16
rc["font.family"] = "Times New Roman"

kde_kernels = NaiveKDE._available_kernels.keys()
fig, axs = pplt.subplots(ncols=3, nrows=3,refwidth=1.5,refheight=1.2)
axs.format(
    abc='a.', abcloc='ul',abcsize=15,
    xlabel='Values', ylabel='Density',
)
for ax, kernel in zip(axs,kde_kernels):
    x,y = NaiveKDE(kernel=kernel,bw=2).fit(data_01).evaluate()
    ax.plot(x,y, lw=1,color="#DB3132")
    ax.fill(x,y,color="#DB3132",alpha=.6)
    # 添加单独数据、
    ax.plot(data_01, [0.005]*len(data_01), '|', color='k',lw=.5)
    ax.format(title=str.capitalize(kernel),titleweight='bold',titlesize=12)
plt.show() 

Gradient color fill

For better visual effects, the original data values ​​used to draw the density map need to be color mapped, that is, a continuous gradient color bar is used to represent the specific drawing value, and the corresponding color is filled within the range of the density map curve. This effect needs to be achieved through custom drawing methods.

The following figure shows density plots filled with gradient colors drawn using Matplotlib, ProPlot, and SciencePlots libraries respectively.

import numpy as np
import pandas as pd
from KDEpy import FFTKDE
from colormaps import parula

#构建数据集
data_01 = [5.1,5.2,5.3,5.4,5.5,6.0,6.2,6.3,6.4,6.5,
           7.0,7.5,8.0,8.5,8.8,8.9,9.0,9.5,10,11,
           11.5,12,13,14,14.5,15,15.5,16,16.5,17]
           
           
#(a)利用Matplotlib绘制的带渐变颜色填充的密度图           
import matplotlib.pyplot as plt
from matplotlib.axes import Axes

plt.rcParams["font.family"] = "Times New Roman"
plt.rcParams["axes.linewidth"] = 1
plt.rcParams["axes.labelsize"] = 15
plt.rcParams["xtick.minor.visible"] = True
plt.rcParams["ytick.minor.visible"] = True
plt.rcParams["xtick.direction"] = "in"
plt.rcParams["ytick.direction"] = "in"
plt.rcParams["xtick.labelsize"] = 12
plt.rcParams["ytick.labelsize"] = 12
plt.rcParams["xtick.top"] = False
plt.rcParams["ytick.right"] = False

x, y = FFTKDE(kernel="gaussian", bw=2).fit(data_01).evaluate()
img_data = x.reshape(1, -1)

cmap = parula
fig,ax = plt.subplots(figsize=(4,3.5),dpi=100,facecolor="w")
ax.plot(x,y, lw=1,color="k")
# 添加单独数据、
ax.plot(data_01, [0.005]*len(data_01), '|', color='k',lw=1)
#ax.tick_params(which="both",direction='in')
ax.set_xlabel("Values")
ax.set_ylabel("Density")
ax.set_title("Gaussian Kernel",size=15)

extent=[*ax.get_xlim(), *ax.get_ylim()]
im = Axes.imshow(ax, img_data, aspect='auto',cmap=cmap,extent=extent)
fill_line,= ax.fill(x, y,facecolor='none')
im.set_clip_path(fill_line)
colorbar = fig.colorbar(im,ax=ax,aspect=12,label="Values")
#colorbar.ax.tick_params(which="both",direction='in')
#colorbar.ax.set_title("Values",fontsize=10)

plt.show()   

#(b)利用ProPlot绘制的带渐变颜色填充的密度图

from colormaps import parula
#from matplotlib.axes import Axes
from proplot.axes import Axes
from proplot import rc

rc["font.family"] = "Times New Roman"
rc["axes.labelsize"] = 15
rc['tick.labelsize'] = 10
rc["suptitle.size"] = 16

x, y = FFTKDE(kernel="gaussian", bw=2).fit(data_01).evaluate()
img_data = x.reshape(1, -1)

cmap = parula
fig = pplt.figure(suptitle="Gaussian",figsize=(3.5,3))
ax = fig.subplot(xlabel='x axis', ylabel='y axis')
ax.format(abc='a.', abcloc='ul',abcsize=16,
          xlabel='Values', ylabel='Density',
          suptitle='Gaussian Kernel')
ax.plot(x,y, lw=1,color="k")
# 添加单独数据、
ax.plot(data_01, [0.005]*len(data_01), '|', color='k',lw=1)
fill_line,= ax.fill(x, y,facecolor='none')
extent=[*ax.get_xlim(), *ax.get_ylim()]
im = Axes.imshow(ax, img_data, aspect='auto',cmap=cmap,extent=extent)
im.set_clip_path(fill_line)
fig.colorbar(im,title="Values",tickminor=True,tickdirection="in")

plt.show()  

#(c)利用SciencePlots 绘制的带渐变颜色填充的密度图

from KDEpy import NaiveKDE
from colormaps import parula
from matplotlib.axes import Axes

customer_ages = [5.1,5.2,5.3,5.4,5.5,6.0,6.2,6.3,6.4,6.5,
                 7.0,7.5,8.0,8.5,8.8,8.9,9.0,9.5,10,11,
                 11.5,12,13,14,14.5,15,15.5,16,16.5,17]
x, y = NaiveKDE(kernel="gaussian",bw=2).fit(customer_ages).evaluate()
img_data = x.reshape(1, -1)
cmap = parula

from matplotlib.axes import Axes
with plt.style.context(['science']):
    fig,ax = plt.subplots(figsize=(4,3.5),dpi=100,facecolor="w")
    ax.plot(x,y, lw=1,color="k")
    # 添加单独数据、
    ax.plot(data_01, [0.005]*len(data_01), '|', color='k',lw=1)
    #ax.tick_params(which="both",direction='in')
    ax.set_xlabel("Values")
    ax.set_ylabel("Density")
    ax.set_title("Gaussian Kernel",size=15)
    ax.text(.05,.88,"a.",transform=ax.transAxes,fontsize=25,fontweight="bold")
    extent=[*ax.get_xlim(), *ax.get_ylim()]
    im = Axes.imshow(ax, img_data, aspect='auto',cmap=cmap,extent=extent)
    fill_line,= ax.fill(x, y,facecolor='none')
    im.set_clip_path(fill_line)
    colorbar = fig.colorbar(im,ax=ax,aspect=12,label="Values")
plt.show() 

It should be noted that the continuous fill color system here is a custom parula color system (MATLAB classic color system). You only need to add the colormaps.py file to the current drawing environment to import the defined parula color system.

For the situation of "multiple sets of data, the same kernel function" or "the same set of data, different kernel functions", the drawing method of the color-filled density map is the same as that of the same set of data.

The figure below shows the gradient color filling density map corresponding to the "same set of data, different kernel functions" drawn using the ProPlot library.

from colormaps import parula
from proplot.axes import Axes
from KDEpy import NaiveKDE
from proplot import rc

rc["font.family"] = "Times New Roman"
rc["axes.labelsize"] = 15
rc['tick.labelsize'] = 10
rc["suptitle.size"] = 16



data_01 = [5.1,5.2,5.3,5.4,5.5,6.0,6.2,6.3,6.4,6.5,
                 7.0,7.5,8.0,8.5,8.8,8.9,9.0,9.5,10,11,
                 11.5,12,13,14,14.5,15,15.5,16,16.5,17]


cmap = parula
kde_kernels = NaiveKDE._available_kernels.keys()
fig, axs = pplt.subplots(ncols=3, nrows=3,refwidth=1.5,refheight=1.2)
axs.format(
    abc='a.', abcloc='ul',abcsize=16,
    xlabel='Values', ylabel='Density',
)
for ax, kernel in zip(axs,kde_kernels):
    x,y = NaiveKDE(kernel=kernel,bw=2).fit(data_01).evaluate()
    img_data = x.reshape(1, -1)
    ax.plot(x,y, lw=1,color="k")
    fill_line,= ax.fill(x, y,facecolor='none')
     # 添加单独数据、
    ax.plot(data_01, [0.005]*len(data_01), '|', color='k',lw=.5)
    ax.format(title=str.capitalize(kernel),titleweight='bold',titlesize=12)
    
    extent=[*ax.get_xlim(), *ax.get_ylim()]
    im = Axes.imshow(ax, img_data, aspect='auto',cmap=cmap,extent=extent)
    im.set_clip_path(fill_line)
    colorbar = fig.colorbar(im,tickminor=True,tickdirection="in",ax=ax)
    colorbar.ax.set_title("Values",fontsize=8)
plt.show() 

"Ridge" diagram

When drawing density charts for multiple sets of data, in addition to using subgraphs to draw each set of data as described above, we can also stack the drawing results of multiple sets of data, that is, use a "ridgeline" chart. to express .

"Ridge" plots are usually used to represent the differences in the distribution of different categories of data on the same factor. In Matplotlib, we can use Matplotlib's "native" method to draw the "ridge" plot, or we can use the JoyPy library to draw it.

sord_index = [i for i in group_data.color.unique()]
sord_index = sorted(sord_index, key=str.lower)
fig,ax = plt.subplots(figsize=(5.5,4.5), dpi=100)
for i,index in zip(range(len(sord_index)), sord_index):
	data = group_data.loc[group_data["color"]==index, "depth"].values
	x,y = NaiveKDE(kernel="Gaussian", bw=.8).fit(data).evaluate()
	ax.plot(x, 6*y+i, lw=.6, color="k", zorder=100-i)
	ax.fill(x, 6*y+i, lw=1, color="gray", alpha=.6, zorder=100-i)
	ax.grid(which="major", axis="y", ls="--", lw=.7, color="gray", zorder=-1)
	ax.yaxis.set_tick_params(labelleft=True)
	ax.set_yticks(np.arange(len(sord_index)))
	ax.set_yticklabels(sord_index)

We can use the JoyPy library to draw the histogram "ridge" plot of each set of data. Just set the parameter hist in the joyplot() function to True. We can also color map the "ridge" plot by setting the colormap parameter.

# 直方"山脊"图的绘制
fig, axes = joypy.joyplot(group_data, by="color",
	column="depth", labels=sord_index, grid="y",
	linewidth=1, figsize=(7,6), color="gray",
	hist=True, xlabelsize=15, ylabelsize=15)
# 渐变颜色填充"山脊"图的绘制
from colormaps import parula
fig, axes = joypy.joyplot(group_data, by="color",
	column="depth", labels=sord_index, grid="y",
	linewidth=1, figsize=(7,6), hist=False,
	colormap=parula, xlabelsize=15, ylabelsize=15)

Since the functionality of the JoyPy library is not yet complete, readers are recommended to use Matplotlib's native method to draw "ridge" plots.

If you want to use a continuous gradient color to fill each set of data in the "ridge" chart, and use a continuous gradient color value to represent the data size, you can refer to the method of drawing a gradient color fill density chart.

It should be noted that because the drawing script involves loop drawing statements, when saving into a vector file (such as a PDF file), cropping failure will occur . To solve this problem, we only need to add the following code before writing the script.

# 在将多个绘图对象保存为PDF文件时,需要进行如下设置
plt.rcParams["image.composite_image"] = False

The picture below is a gradient color-filled "ridge" diagram drawn using Matplotlib. Picture (a) uses the color mapping style "plasma", and picture (b) uses the color mapping style "parula". Different colors represent different variables ( Depth) value size.

# 在将多个绘图对象保存为PDF文件时,需要进行如下设置
plt.rcParams["image.composite_image"] = False
fig,ax = plt.subplots(figsize=(5.5, 4.5), dpi=100)
for i,index in zip(range(len(sord_index)), sord_index):
	data = group_data.loc[group_data["color"]
		==index,"depth"].values
	x,y = NaiveKDE(kernel="Gaussian", bw=.8).
		fit(data).evaluate()
	img_data = x.reshape(1, -1)
	ax.plot(x,6*y+i, lw=1, color="k", zorder=100-i)
	fill_line, = ax.fill(x, 6*y+i, facecolor="none")
	ax.grid(which="major", axis="y", ls="--",
		lw=.7, color="gray", zorder=-1)
	ax.set_xlim(50,72)
	ax.yaxis.set_tick_params(labelleft=True)
	ax.set_yticks(np.arange(len(sord_index)))
	ax.set_yticklabels(sord_index)
	ax.set_xlabel("Depth")
	ax.set_ylabel("Color")
	ax.tick_params(which ="both",top=False,right=False)
	ax.tick_params(which = "minor", axis="both", left=False,
		bottom=False)
for spin in ["top", "right", "bottom", "left"]:
	ax.spines[spin].set_visible(False)
	extent=[*ax.get_xlim(), *ax.get_ylim()]
	im = Axes.imshow(ax, img_data, aspect='auto',
		cmap="plasma", extent=extent)
	im.set_clip_path(fill_line)
colorbar = fig.colorbar(im, aspect=10, shrink=0.5)
colorbar.ax.set_title("Values", fontsize=10)

Gradient color filled "ridge" plots plotted using the ProPlot and SciencePlots libraries respectively.

import pandas as pd
import numpy as np
import proplot as pplt

group_data = pd.read_csv(r"第3章 单变量图形的绘制\山脊图绘制数据.csv")
sord_index = [i for i in group_data.color.unique()]
sord_index = sorted(sord_index,key=str.lower)


# a)利用ProPlot绘制的渐变颜色填充“山脊”图(fire)
from proplot.axes import Axes
from proplot import rc
rc["font.family"] = "Times New Roman"
rc["axes.labelsize"] = 15
rc['tick.labelsize'] = 10
rc["suptitle.size"] = 16
rc["image.composite_image"] = False

fig = pplt.figure(figsize=(5.,4.5))
ax = fig.subplot()
ax.format(xlabel='Depth', ylabel='Color',ytickminor=False)
for i,index in zip(range(len(sord_index)),sord_index):
    data = group_data.loc[group_data["color"]==index,"depth"].values
    x,y = NaiveKDE(kernel="Gaussian",bw=.8).fit(data).evaluate()
    img_data = x.reshape(1,-1)
    ax.plot(x,6*y+i, lw=1,color="k",zorder=100 - i)
    fill_line, = ax.fill(x,6*y+i,facecolor="none")
    ax.yaxis.set_tick_params(labelleft=True)
    ax.set_yticks(np.arange(len(sord_index)))
    ax.set_yticklabels(sord_index)
    
    extent=[*ax.get_xlim(), *ax.get_ylim()]
    #im = Axes.imshow(ax, img_data, aspect='auto',cmap=cmap,extent=extent) Fire
    im = Axes.imshow(ax, img_data, aspect='auto',cmap="Fire",extent=extent)
    im.set_clip_path(fill_line)

colorbar = fig.colorbar(im,tickminor=True,tickdirection="in",length=.5,width=.2)
colorbar.ax.set_title("Values",fontsize=8)
plt.show()  

#b)利用SciencePlots绘制的渐变颜色填充“山脊”图(plasma)

from matplotlib.axes import Axes
# 保存多个ax为pdf文件需要设置
plt.rcParams["image.composite_image"] = False
with plt.style.context(['science']):
    fig,ax = plt.subplots(figsize=(5.5,4.5),dpi=100,facecolor="w")
    for i,index in zip(range(len(sord_index)),sord_index):
        data = group_data.loc[group_data["color"]==index,"depth"].values
        x,y = NaiveKDE(kernel="Gaussian",bw=.8).fit(data).evaluate()
        img_data = x.reshape(1,-1)
        ax.plot(x,6*y+i, lw=1,color="k",zorder=100 - i)
        fill_line, = ax.fill(x,6*y+i,facecolor="none")
        #ax.axhline(i,ls="--",lw=.7,color="gray",zorder=100 - i)
        ax.grid(which="major",axis="y",ls="--",lw=.7,color="gray",zorder=-1)
        #ax.set_xlim(50,72)
        ax.yaxis.set_tick_params(labelleft=True)
        ax.set_yticks(np.arange(len(sord_index)))
        ax.set_yticklabels(sord_index)
        ax.set_xlabel("Depth")
        ax.set_ylabel("Color")
        ax.tick_params(which ="both",top=False,right=False)
        ax.tick_params(which = "minor",axis="both",left=False,bottom=False)
        for spin in ["top","right","bottom","left"]:
            ax.spines[spin].set_visible(False)
        extent=[*ax.get_xlim(), *ax.get_ylim()]
        im = Axes.imshow(ax, img_data, aspect='auto',cmap="plasma",extent=extent)
        im.set_clip_path(fill_line)
    colorbar = fig.colorbar(im,aspect=10,shrink=0.5)
    colorbar.ax.set_title("Values",fontsize=10)
plt.show() 

Drawing of multiple density maps in the same coordinate system

When drawing multiple density plots in the same coordinate system, in addition to using the Matplotlib library for loop drawing, you can also use the Seaborn library for fast drawing.

The picture below shows "multiple density plots in the same coordinate system" drawn using Matplotlib and Seaborn respectively.

# 利用Matplotlib 绘制
from scipy import stats
palette = ["#352A87", "#108ED2", "#65BE86", "#FFC337"]
fig,ax = plt.subplots(figsize=(4, 3.5), dpi=100)
for i, index, color in
	zip(range(len(palette)), data_df.columns, palette):
		data = data_df[index].values
		density = stats.kde.gaussian_kde(data)
		x = np.linspace(-2, 25, 500)
		y = density(x)
		ax.plot(x, y, lw=.5, color="k", zorder=5-i)
		ax.fill(x, y, color=color, label=index, alpha=.7)
ax.set_xlabel("Values")
ax.set_ylabel("Density")
ax.legend()

# 利用Seaborn绘制
fig,ax = plt.subplots(figsize=(4, 3.5), dpi=100)
sns.kdeplot(data=data_df, shade=True, palette= palette, alpha=.6, ax=ax)
ax.set_xlabel("Values")

Note that the default order of multiple density plots in the same coordinate system drawn with Seaborn is different from the Matplotlib drawing results.

When drawing Seaborn drawing objects in the editing environment of the ProPlot library, although both are advanced packaging libraries developed based on Matplotlib, there are still major differences between the two and they cannot be unified in specific graphics drawing. The syntax standard causes the ProPlot library to have weak drawing customization operations when drawing Seaborn graphics objects.

The picture below shows "multiple density plots in the same coordinate system" drawn using ProPlot and SciencePlots libraries respectively.

import pandas as pd
import numpy as np
from scipy import stats
import matplotlib.pyplot as plt

data_01 = [5.1,5.2,5.3,5.4,5.5,6.0,6.2,6.3,6.4,6.5,
           7.0,7.5,8.0,8.5,8.8,8.9,9.0,9.5,10,11,
           11.5,12,13,14,14.5,15,15.5,16,16.5,17]

data_02 = [5.1,5.2,5.3,5.4,5.5,6.0,7.0,7.3,7.4,7.5,
           8.0,8.2,8.4,8.6,8.8,9.0,9.2,9.4,9.6,9.8,
           10,10.2,11,11.5,12,12.5,13,13.5,15,16]
data_03 = [5.1,5.2,5.3,5.4,5.6,6.0,6.1,6.2,6.4,6.8,
           7.1,8.2,8.8,9.0,9.2,10.2,10.4,10.8,11,11.6,
           12,12.4,12.6,12.8,13,13.2,13.4,13.6,13.7,13.8]

data_04 = [5.0,5.2,5.3,5.4,5.6,5.8,6.0,6.2,6.4,6.6,
             6.8,7.0,7.2,7.4,7.6,8.0,9.0,9.2,9.6,9.8,
             10,10.3,11,12,16,16,18,18.5,19,22]
data_df = pd.DataFrame({
    
    "data_01":data_01,"data_02":data_02,
                        "data_03":data_03,"data_04":data_04})


#a)利用ProPlot 绘制的结果  

from scipy import stats
from proplot import rc
rc["axes.labelsize"] = 15
rc['tick.labelsize'] = 12
rc["suptitle.size"] = 15
palette = ["#352A87","#108ED2","#65BE86","#FFC337"]

fig = pplt.figure(figsize=(3.5,3))
ax = fig.subplot()
ax.format(abc='a.', abcloc='ul',abcsize=16,
          xlabel='Values', ylabel='Density')

for i, index,color in zip(range(len(palette)),data_df.columns,palette):
    data = data_df[index].values
    density = stats.kde.gaussian_kde(data)
    x = np.linspace(-2,25,500)
    y = density(x)
    ax.plot(x,y, lw=.5,color="k",zorder=5-i)
    ax.fill(x,y,color=color,label=index,alpha=.7)
ax.legend(ncols=1,frame=False,loc='ur')

plt.show() 


#b)利用ProPlot seaborn对象绘制的结果 

from proplot import rc
rc["axes.labelsize"] = 15
rc['tick.labelsize'] = 10
rc["suptitle.size"] = 16
rc["legend.fontsize"] = 5

palette = ["#352A87","#108ED2","#65BE86","#FFC337"]

fig = pplt.figure(figsize=(3.5,3))
ax = fig.subplot()
ax.format(abc='a.', abcloc='ul',abcsize=16,
          xlabel='Values', ylabel='Density')

sns.kdeplot(data=data_df,shade=True,palette = palette,alpha=.6,ax=ax)
plt.show() 

#c)利用SciencePlots绘制的结果 使用全局变量设置,字体显示正常

import matplotlib.pyplot as plt
plt.style.use('science')

from scipy import stats
palette = ["#352A87","#108ED2","#65BE86","#FFC337"]
titles = ["Type One","Type Two","Type Three","Type Four"]
fig,ax = plt.subplots(figsize=(4,3.5),dpi=100,facecolor="w")
for i, index,color,label in zip(range(len(palette)),data_df.columns,palette,titles):
    data = data_df[index].values
    density = stats.kde.gaussian_kde(data)
    x = np.linspace(-2,25,500)
    y = density(x)
    ax.plot(x,y, lw=.5,color="k",zorder=5-i)
    ax.fill(x,y,color=color,label=label,alpha=.7)
ax.set_xlabel("Values")
ax.set_ylabel("Density")
ax.legend()

plt.show() 

Reference books: Ning Haitao. Guide to illustrating scientific research papers - based on Python[M]. Beijing: People's Posts and Telecommunications Press, 2023: 49-58.

Guess you like

Origin blog.csdn.net/m0_52316372/article/details/132639785
Map
Map
map
map