当前位置:首页>python>期刊图片复现|Python绘制堆叠图+云雨图+箱线图组合图展示数据分布情况

期刊图片复现|Python绘制堆叠图+云雨图+箱线图组合图展示数据分布情况

  • 2026-10-25 15:10:57
期刊图片复现|Python绘制堆叠图+云雨图+箱线图组合图展示数据分布情况

代码绘制成果展示

论文:Enhanced accessibility to park cooling services in developed areas: Experimental insights on the walkability in large urban agglomerations
论文原图
这张图详细展示了长三角城市群中城市公园的数量分布及其降温效应的统计特征,分为三个部分:图a通过堆叠条形图统计了26个城市的公园总数,其中深绿色条形代表具有显著降温效应的公园数量,灰色条形代表无显著降温效应的公园;图b利用云雨图对比了五类不同规模城市在四个关键降温指标上的表现,这四个指标分别是最大降温幅度(PCM)、最大降温距离(PCD)、公园降温强度(PCI)和公园降温梯度(PCG);图c进一步利用箱线图展示了具体的26个城市在上述四个指标上的数据分布,箱体覆盖了25%-75%的数据范围,内部黑线代表中位数,红色三角形代表均值,蓝色折线连接了各城市的均值以显示趋势,上下须线代表1.5倍四分位距的范围,不同颜色的箱体对应不同的城市规模分类 。
仿图
多种配色

代码解释

第一部分

库的导入以及字体设置
# =========================================================================================# ====================================== 1. 环境设置 =======================================# =========================================================================================import matplotlib.pyplot as pltimport matplotlib.patches as patchesimport matplotlib.lines as mlinesimport matplotlib.gridspec as gridspecimport pandas as pdimport numpy as npimport seaborn as snsimport osfrom scipy import statsimport matplotlibplt.rcParams['font.family'] = 'serif'plt.rcParams['font.serif'] = ['Times New Roman']plt.rcParams['axes.unicode_minus'] = Falsesns.set_context("notebook")sns.set_style("ticks")matplotlib.rcParams['pdf.fonttype'] = 42matplotlib.rcParams['ps.fonttype'] = 42

第二部分

颜色库的设置、绘图结果保存文件夹地址设置,颜色方案选择
# =========================================================================================# ======================================2.颜色库=======================================# =========================================================================================COLOR_SCHEMES = {    # =================原有单色渐变/近似色系 (1-20)=================    1: ["#405163", "#536D7A", "#688A90", "#8CB2A6", "#C4D8CB", "#40686A", "#959595", "#2F4F4F"],}scheme_index  = 39 #当前使用的颜色方案CUSTOM_COLORS = COLOR_SCHEMES.get(scheme_index, COLOR_SCHEMES[1])  # 获取颜色列表OUTPUT_DIR = r'组合图'  #结果输出路径FRAME_LINEWIDTH = 1.5  # 边框宽度

第三部分

堆叠条形图绘制函数
# =========================================================================================# ======================================3.堆叠条形图绘制函数=======================================# =========================================================================================def render_panel_a(ax, df):    df_sorted = df.sort_values("Total", ascending=True).reset_index(drop=True)  # 将数据按列升序排序    color_sig = CUSTOM_COLORS[5]  #显著部分颜色    color_ns = CUSTOM_COLORS[6]  #非显著部分颜色    y_pos = range(len(df_sorted))  # 生成Y轴的位置序列,长度等于数据行数    # 绘制水平条形图    ax.barh(y_pos,#位置            df_sorted["Significant"],  #数值            color=color_sig,  #颜色            height=0.75,  # 条形的高度            label='Show a cooling effect')  #图例标签    # 绘制第二组水平条形图(堆叠部分)    ax.barh(y_pos,  #位置            df_sorted["Not_Significant"],  #数值            left=df_sorted["Significant"],  # 设置起始位置在显著条形的右侧,实现堆叠效果            color=color_ns,  # 颜色            height=0.75,  #条形的高度            label='No significant cooling effect')  #图例标签    # 配置X轴的刻度参数    ax.tick_params(axis='x',                   direction='out',  # 刻度线朝外                   labelsize=22)  # 字体大小    # 配置Y轴的刻度参数    ax.tick_params(axis='y',                   length=0,  # 刻度线长度                   labelsize=22)  # 字体大小    box_height = 1  #顶部图框高度    box_y_start = len(df_sorted) - 0.4  #灰色方框的起始Y坐标    # 创建一个矩形    rect = patches.Rectangle((0, box_y_start),  # 起始坐标                             x_limit,  # 矩形宽度                             box_height,  # 矩形高度                             linewidth=1,  # 边框线宽                             edgecolor='black',  # 边框颜色                             facecolor='#A9A9A9',  #填充颜色                             alpha=1,  # 透明度                             clip_on=False)  # 允许矩形超出坐标轴范围显示    ax.add_patch(rect)  # 将矩形添加到坐标轴上    # 设置子图编号    ax.text(-0.45,  #X            1.00,  # Y            'a',  #内容            transform=ax.transAxes,  #相对坐标系            fontsize=30,  #字体大小            fontweight='normal',  # 字体粗细            va='top',  # 垂直对齐            fontname='Times New Roman')    ax.spines['top'].set_visible(False)  # 隐藏顶部边框    ax.spines['right'].set_visible(False)  # 隐藏右侧边框

第四部分

半小提琴图绘制函数,一个辅助函数,用于绘制“云雨图”中的“云”部分(即数据的分布密度)。核密度估计,通过bw_method 控制曲线的平滑的程度。填充密度曲线下方的区域,形成半个小提琴的形状。计算中位数,并在密度图上画一条白色的虚线,指示数据的中心位置
不同的平滑程度的出图效果
# =========================================================================================# ======================================4.半小提琴图绘制函数=======================================# =========================================================================================def draw_half_violin(ax, data, pos, color, width=0.5):    density = stats.gaussian_kde(data, bw_method=0.08)  # 使用高斯核密度估计计算数据的密度    xs = np.linspace(min(data), max(data), 200)  # 在数据最小值和最大值之间生成均匀分布的点作为X轴    ys = density(xs)  # 计算这些点对应的密度值作为Y轴    ys = ys / ys.max() * width  # 将密度值归一化并缩放到指定的宽度    ax.vlines(median_val,  # x轴坐标              pos,  # 垂直线的起始y坐标              pos + median_height,  # 垂直线的结束y坐标              color='white',  # 线条颜色              linestyle='--',  # 线条样式              linewidth=1.2,  # 线条宽度设              alpha=1.0,  # 透明度              zorder=2)

第五部分

云雨图绘制函数,包含分布曲线、箱线图和散点图。循环绘图: 针对4个指标创建2x2 的子图。
云雨图组合:
云(分布): 调用小提琴图绘制函数来进行绘制。
箱(统计): 使用ax.boxplot绘制水平箱线图,去掉了离群点。
雨(散点): 使用 ax.scatter 绘制原始数据点,并增加了随机抖动,防止点重叠在一起。
# =========================================================================================# ======================================5.云雨图绘制函数=======================================# =========================================================================================def render_panel_b(fig, gs_base, df):    # 定义指标信息列表,包含名称、单位、X轴范围、X轴刻度    metrics_info = [        ("PCM", "°C", (0, 7.5), [0, 1, 2, 3, 4, 5, 6, 7]),        ("PCD", "m", (0, 330), [0, 100, 200, 300]),        ("PCI", "", (0, 0.07), [0, 0.02, 0.04, 0.06]),        ("PCG", "", (0, 2.2), [0, 1, 2])    ]    categories = ["Megacity", "Large City", "Medium City I", "Medium City II", "Small City"]  # 定义区域分类列表    categories_rev = categories[::-1]  # 将分类列表反转    y_positions = np.arange(len(categories))  # 生成Y轴位置索引    color_map = {cat: col for cat, col in zip(categories, CUSTOM_COLORS[:5])}  # 创建类别到颜色的映射字典            if len(cat_data) == 0:  # 如果没有数据,则跳过                continue                             width=0.45)  # 宽度            # 绘制箱线图            ax.boxplot([cat_data],  # 数据                       positions=[y_base + 0.08],  # 箱线图位置                       vert=False,  # 水平方向                       widths=0.15,  #箱体宽度                       patch_artist=True,  # 填充颜色                       showfliers=False,  # 不显示离群点                       showcaps=False,  # 不显示箱线图的帽子                       medianprops={"color": "black",  # 中位数线颜色                                    "linewidth": 1},  # 中位数线宽                       boxprops={"facecolor": color,  # 箱体填充颜色                                 "edgecolor": "black",  # 箱体边框颜色                                 "linewidth": 1,  # 箱体边框线宽                                 "alpha": 0.8},  # 透明度                       whiskerprops={"color": "black",  # 须线颜色                                     "linewidth": 1})  # 须线宽度            jitter = np.random.uniform(-0.15, 0.0, size=len(cat_data))  # 生成随机抖动值            median_bg_color = CUSTOM_COLORS[7]  # 获取用于散点的颜色            # 绘制散点图            ax.scatter(cat_data,  # x轴数据                       y_base + jitter - 0.05,  # y轴数据                       s=6,  # 散点的大小                       color=median_bg_color,  # 散点的颜色                       alpha=0.5,  # 透明度                       zorder=0)         # 设置子图标题        ax.set_title(metric,  #名称                     fontsize=20,  #字体大小                     pad=10,  # 标题距离                     fontweight='bold')  #加粗        #设置X轴标签单位        ax.set_xlabel(unit,loc='right',labelpad=-16, fontweight='bold', fontname='Times New Roman',fontsize=22)        ax.set_xlim(xlim)  # X轴范围            ax.set_yticklabels(categories_rev, fontsize=22)  # 显示类别名称作为Y轴标签            ax.tick_params(axis='y', length=0)  # Y轴刻度线长度            ax.spines['left'].set_visible(False)  # 隐藏图框        ax.spines['top'].set_visible(False)  # 隐藏顶部图框        ax.spines['right'].set_visible(False)  # 隐藏右侧图框        ax.spines['bottom'].set_visible(True)  # 显示底部图框        # 显示网格线        ax.grid(axis='x',  # X轴                color='lightgrey',  # 网格线颜色                linestyle='-',  # 网格线样式                linewidth=0.5,  # 网格线                alpha=0.5)  # 网格线    pass

第六部分

箱线图绘制函数,分为左右两部分(左侧的图例,右侧的箱线图)。图例包括:颜色、25%-75% 区间、中位数线、均值点(三角形)、1.5IQR 范围线等。箱线图:展示数据分布,均值连线以蓝色折线展示城市间的变化趋势。
# =========================================================================================# ======================================6.箱线图绘制函数=======================================# =========================================================================================def render_panel_c(fig, gs_base, df, cities):    # 创建子网格布局    gs_c = gridspec.GridSpecFromSubplotSpec(1,  #行                                            2,  #列                                            subplot_spec=gs_base,  # 基于基础网格                                            width_ratios=[1, 2.4],  # 左右列宽度比例                                            wspace=0.1)  # 水平间距    ax_text = fig.add_subplot(gs_c[0])  # 在左侧网格添加子图用于显示文本和图例    ax_text.axis('off')  # 关闭坐标轴显示    # 设置子图编号    ax_text.text(-0.05,  #X                 1.02,  # Y                 'c',  # 文本内容                 fontsize=28,  # 字体大小                 fontweight='normal',  # 字体粗细                 transform=ax_text.transAxes,  # 使用相对坐标系                 fontname='Times New Roman')    #图例内容设置    col_1 = ["01.Shanghai", "02.Hangzhou", "03.Nanjing", "04.Suzhou", "05.Hefei", "06.Ningbo", "07.Wuxi","08.Changzhou", "09.Shaoxing"]    col_2 = ["10.Nantong", "11.Yangzhou", "12.Yancheng", "13.Tāizhou", "14.Wuhu", "15.Jiaxing", "16.Tàizhou","17.Ma'anshan", "18.Zhenjiang"]    col_3 = ["19.Jinhua", "20.Huzhou", "21.Anqing", "22.Zhoushan", "23.Tongling", "24.Chuzhou", "25.Chizhou","26.Xuancheng"]    all_cols = [col_1, col_2, col_3]  #合成一个列表    col_x_positions = [0.0, 0.35, 0.70]  #设置三列的X坐标位置    for col_idx, city_list in enumerate(all_cols):  # 遍历每一列        x_pos = col_x_positions[col_idx]  # 获取当前列的X坐标        for row_idx, city_name in enumerate(city_list):  # 遍历当前列的每一个元素            y_pos = 0.98 - row_idx * 0.055 #Y坐标            # 在指定位置绘制文本            ax_text.text(x_pos,  # X坐标                         y_pos,  # Y坐标                         city_name,  # 内容                         fontsize=22,  # 字体大小                         transform=ax_text.transAxes,  # 使用相对坐标                         ha='left')  # 左对齐    legend_start_y = 0.35  # 设置图例部分的起始Y坐标    legend_gap_y = 0.07  # 设置图例条目间的垂直间距    text_offset_x = 0.12  # 设置图例文字的X轴偏移量    cat_names = ["Megacity", "Large City", "Medium City I", "Medium City II", "Small City"]  # 类别名称列表    # =======================================================    # ======================颜色图例==========================    # =======================================================    legend_right_x = 0.55  # 右侧图例的起始X坐标    legend_right_text_offset = 0.12  # 右侧图例文字的偏移量    for i, (name, color) in enumerate(zip(cat_names, CUSTOM_COLORS[:5])):  # 遍历类别和对应的颜色        y_loc = legend_start_y - i * legend_gap_y  # 计算当前条目的Y坐标        # 绘制颜色矩形块        ax_text.add_patch(patches.Rectangle((legend_right_x, y_loc),  #坐标                                            0.1,  # 宽度                                            0.04,  # 高度                                            facecolor=color,  # 填充颜色                                            edgecolor='none',  #无边框                                            transform=ax_text.transAxes))  # 使用相对坐标        # 绘制类别名称文本        ax_text.text(legend_right_x + legend_right_text_offset,  # x                     y_loc + 0.02,  # Y                     name,  # 名称                     transform=ax_text.transAxes,  # 使用相对坐标                     fontsize=22,  # 字体大小                     va='center')  # 垂直居中    # =======================================================    # ======================25-75图例图例==========================    # =======================================================    y1 = legend_start_y  # Y坐标    # 绘制白色矩形    ax_text.add_patch(patches.Rectangle((0.0, y1),  # 坐标                                        0.1,  # 宽度                                        0.04,  # 高度                                        facecolor='white',  # 填充                                        edgecolor='black',  #边框                                        linewidth=1.2,  # 线宽                                        transform=ax_text.transAxes))  # 相对坐标    # 绘制说明文本    ax_text.text(text_offset_x,  #x                 y1 + 0.02,  # Y                 "25%-75%",  # 文本                 transform=ax_text.transAxes,  # 相对坐标                 fontsize=22,  # 字体大小                 va='center')  # 垂直居中    # =======================================================    # ======================中值线图例图例==========================    # =======================================================    y2 = y1 - legend_gap_y  # Y坐标    median_bg_color = CUSTOM_COLORS[7]  # 获取颜色   # 线宽                               transform=ax_text.transAxes)  # 相对坐标    ax_text.add_line(line_white)  # 将线条添加到子图    ax_text.text(text_offset_x,  # 绘制说明文本                 y2 + 0.02,  # Y坐标                 "Median Line",  # 文本内容                 transform=ax_text.transAxes,  # 相对坐标                 fontsize=22,  # 字体大小                 va='center')  # 垂直居中    # =======================================================    # ======================均值图例图例==========================    # =======================================================    y3 = y2 - legend_gap_y  # Y坐标    # 绘制散点    ax_text.scatter([0.05],  # x                    [y3 + 0.02],  # Y                               [y4 + 0.02, y4 + 0.02],  # Y                               color='black',  # 颜色                               linewidth=1.2,  # 线宽                               transform=ax_text.transAxes)  # 相对坐标    ax_text.add_line(line_range)  # 添加线条    # 左侧垂直短线    ax_text.add_line(        mlines.Line2D([0.0, 0.0],  # X坐标                      [y4 + 0.005, y4 + 0.035],  # Y坐标                      color='black',  # 颜色                      linewidth=1.2,  # 线宽                      transform=ax_text.transAxes))  # 相对坐标    # 右侧垂直短线    ax_text.add_line(        mlines.Line2D([0.1, 0.1],  # X坐标                      [y4 + 0.005, y4 + 0.035],  # Y坐标范围                      color='black',  # 颜色                      linewidth=1.2,  # 线宽                      transform=ax_text.transAxes))  # 相对坐标    ax_text.text(text_offset_x,  # X                 y5 + 0.02,  # Y坐标                 "Connecting line Mean",  # 文本内容                 transform=ax_text.transAxes,  # 相对坐标                 fontsize=22,  # 字体大小                 va='center')  # 垂直居中    # 创建图表部分的子网格    gs_plots = gridspec.GridSpecFromSubplotSpec(2,  # 行                                                2,  # 列                                                subplot_spec=gs_c[1],  # 基于右侧网格                                                wspace=0.15,  # 水平间距                                                hspace=0.2)  # 垂直间距    # 定义指标信息列表    metrics = [        ("PCM", "PCM(°C)", (0, 9)),        ("PCD", "PCD(m)", (0, 350)),        ("PCI", "PCI", (0, 0.065)),        ("PCG", "PCG", (0, 2.5))    ]                    palette=palette,  #颜色                    hue='City_ID',  # 按照ID着色                    legend=False,  # 不显示图例                    width=0.7,  # 箱体宽度                    linewidth=0.8,  # 线宽                    fliersize=1,  # 离群点大小                    showfliers=False,  # 不显示离群点                    boxprops=dict(alpha=0.9,  # 透明度                                  edgecolor='white'),  # 边框颜色                    medianprops=dict(color='white',  # 中位数线颜色                                     linewidth=1))  # 中位数线宽        ax.tick_params(axis='x', length=0)  # 去掉X轴刻度线        ax.tick_params(axis='y', length=0, labelsize=22)  # 去掉Y轴刻度线        for spine in ax.spines.values():  # 遍历所有图框            spine.set_visible(True);  # 显示图框            spine.set_color('black');  # 设置图框颜色            spine.set_linewidth(FRAME_LINEWIDTH)  # 设置图框线宽

第七部分

组合图绘制函数,创建一个大画布将前面的云雨图、堆叠图、箱线图组合到一起并保存下来
# =========================================================================================# ======================================7.组合图绘制函数=======================================# =========================================================================================def draw_combined_figure(df_a, df_b, df_c, cities_c):    fig = plt.figure(figsize=(30, 24))  # 创建画布,    # 创建主网格    main_gs = gridspec.GridSpec(2,  # 行                                1,  # 列                                figure=fig,  # 画布                                height_ratios=[1.2, 1],  # 高度比例                                hspace=0.1)  # 垂直间距    # 创建顶部子网格    top_gs = gridspec.GridSpecFromSubplotSpec(1,  #行                                              2,  # 列                                              subplot_spec=main_gs[0],  # 位于主网格第0行                                              width_ratios=[1, 2.5],  # 宽度比例                                              wspace=0.1)  # 水平间距    ax_a = fig.add_subplot(top_gs[0])  # 在顶部左侧添加子图A                    1.02,  # Y坐标                    'b',  # 文本                    transform=ax_b_proxy.transAxes,  # 相对坐标                    fontsize=28,  # 字体大小                    fontweight='normal',  # 字体粗细                    va='top',  # 顶部对齐                    fontname='Times New Roman')    ax_b_proxy.axis('off')    render_panel_c(fig, main_gs[1], df_c, cities_c)  # 绘制图C    plt.subplots_adjust(left=0.07, right=0.98, top=0.96, bottom=0.04)  # 调整画布的边距    #保存    out_png = os.path.join(OUTPUT_DIR, f'Figure_Combined_Scheme_{scheme_index}.png')    out_pdf = os.path.join(OUTPUT_DIR, f'Figure_Combined_Scheme_{scheme_index}.pdf')    plt.savefig(out_png, dpi=300)    plt.savefig(out_pdf)

第八部分

单独的子图绘制以及保存的函数
# =========================================================================================# ======================================8.子图保存函数=======================================# =========================================================================================def save_individual_figures(df_a, df_b, df_c, cities_c):    fig_a, ax_a = plt.subplots(figsize=(10, 15))  # 创建图A的画布和轴    render_panel_a(ax_a, df_a)  # 绘制图A    plt.tight_layout()  # 调整布局    # 保存    fig_a.savefig(os.path.join(OUTPUT_DIR, f'Figure_A_Scheme_{scheme_index}.png'), dpi=300)    plt.close(fig_a)    fig_b = plt.figure(figsize=(18, 12))  # 创建图B的画布    gs_b = gridspec.GridSpec(1, 1)[0]  # 创建图B的网格    render_panel_b(fig_b, gs_b, df_b)  # 绘制图B    fig_b.text(0.02,  # X坐标               0.95,  # Y坐标               'b',  # 文本               fontsize=28,  # 字体大小               fontweight='normal',  # 字体粗细               fontname='Times New Roman')    plt.tight_layout()  # 调整布局    # 保存    fig_b.savefig(os.path.join(OUTPUT_DIR, f'Figure_B_Scheme_{scheme_index}.png'), dpi=300)    plt.close(fig_b)    fig_c = plt.figure(figsize=(25, 12))  # 创建图C的画布    gs_c = gridspec.GridSpec(1, 1)[0]  # 创建图C的网格    render_panel_c(fig_c, gs_c, df_c, cities_c)  # 绘制图C    plt.tight_layout()  # 调整布局    # 保存    fig_c.savefig(os.path.join(OUTPUT_DIR, f'Figure_C_Scheme_{scheme_index}.png'), dpi=300)    plt.close(fig_c)

第九部分

数据读取以及执行绘图的部分
# =========================================================================================# ======================================9.子图保存函数=======================================# =========================================================================================if __name__ == "__main__":    # 读取数据    df_a = pd.read_excel(r'data_a.xlsx')    df_b = pd.read_excel(r'data_b.xlsx')    df_c = pd.read_excel(r'data_c.xlsx')    # 定义信息列表,包含ID、名称和类别索引    cities_c = [        (1, "Shanghai", 0), (2, "Hangzhou", 1), (3, "Nanjing", 1),        (4, "Suzhou", 2), (5, "Hefei", 2), (6, "Ningbo", 2), (7, "Wuxi", 2), (8, "Changzhou", 2), (9, "Shaoxing", 2),        (10, "Nantong", 3), (11, "Yangzhou", 3), (12, "Yancheng", 3), (13, "Taizhou", 3), (14, "Wuhu", 3),        (15, "Jiaxing", 4), (16, "Taizhou", 4), (17, "Ma'anshan", 4), (18, "Zhenjiang", 4), (19, "Jinhua", 4),        (20, "Huzhou", 4), (21, "Anqing", 4), (22, "Zhoushan", 4), (23, "Tongling", 4), (24, "Chuzhou", 4),        (25, "Chizhou", 4), (26, "Xuancheng", 4)    ]    draw_combined_figure(df_a, df_b, df_c, cities_c)  # 执行绘制组合图函数    save_individual_figures(df_a, df_b, df_c, cities_c)  # 执行子图保存函数

如何应用到你自己的数据

1.设置颜色方案:

scheme_index  = 39 #当前使用的颜色方案

2.设置绘图结果的保存地址:

OUTPUT_DIR = r'组合图'  #结果输出路径

3.读取原始数据:

df_a = pd.read_excel(r'data_a.xlsx')

推荐

期刊图片复现|Python绘制二维偏依赖PDP图
期刊复现|python绘制基于SHAP分析和GAM模型拟合的单特征依赖图
期刊图片复现|python绘制带有渐变颜色shap特征重要性组合图(条形图+蜂巢图)
期刊复现|用Python绘制SHAP特征重要性总览图、依赖图、双特征交互效应SHAP图,解锁XGBoost模型的终极奥秘
期刊图片复现|Python绘制shap重要性蜂巢图+单特征依赖图+交互效应强度气泡图+交互效应依赖图(回归+二分类+分类)

获取方式

公众号中的所有所有的免费代码都已经下架了,都并入到付费部分里了,付费合集代码和数据的购买通道已经开通,全部合集100元,后续将会持续更新,决定购买请后台私信我,注意只会分享练习数据和代码文件,不会提供答疑服务,代码文件中已经包含了每行代码的完整注释,购买前请确保真的需要!!!

最新文章

随机文章