当前位置:首页>python>期刊图片复现|Python绘制百分比堆叠图+内嵌饼图+箱线图组合图

期刊图片复现|Python绘制百分比堆叠图+内嵌饼图+箱线图组合图

  • 2026-10-11 07:06:50
期刊图片复现|Python绘制百分比堆叠图+内嵌饼图+箱线图组合图

代码绘制成果展示

论文:Carbon emission peaks in countries worldwide and their national drivers
论文原图
这张图详细展示了1990年至2020年间全球及排名前十国家的CO2排放贡献结构(A)以及五大排放源的贡献分布趋势(B)。在A中,每个子图左侧的堆叠柱状图列出了当年排放量最大的十个国家及其具体的年排放总量,柱子的长度代表排放规模,不同颜色的色块代表各行业在国家总排放中的占比;各子图嵌入的饼图则汇总了全球层面的平均排放结构占比。B通过箱线图结合散点图的形式,细化展示了这五大行业在所有研究国家中的排放占比分布及其随时间的演变,其中箱体代表数据的四分位分布,散点代表具体国家。
仿图
多种配色方案

代码解释

第一部分

库的导入以及字体设置
# =========================================================================================# ====================================== 1. 库的导入 =========================================# =========================================================================================import matplotlib.pyplot as pltimport numpy as npimport pandas as pdimport matplotlib.gridspec as gridspecfrom matplotlib.patches import Rectangleimport matplotlibplt.rcParams['font.family'] = 'serif'plt.rcParams['font.serif'] = ['Times New Roman']matplotlib.rcParams['pdf.fonttype'] = 42matplotlib.rcParams['ps.fonttype'] = 42

第二部分

颜色库的设置
# =========================================================================================# ====================================== 2.颜色库=========================================# =========================================================================================COLOR_SCHEMES = {    1: ['#7b97c3', '#e8a97d', '#f7e193', '#e9a7b9', '#92b995'],}

第三部分

内嵌3D饼图的绘制函数,通过绘制多个饼图堆叠在一起同时压缩纵横比来实现在视觉上形成内嵌3D的效果
# =========================================================================================# ======================================3.内嵌的3D饼图绘制函数=========================================# =========================================================================================def draw_3d_pie(parent_ax, data, palette, title="Global"):    explode = [0.08] * len(data)  #饼图分裂效果    start_angle = -240  #绘制的起始角度    aspect_ratio = 0.5  #纵横比    thickness_factor = 0.01  #每一层饼图的厚度因子    for i in range(1, 35):  #循环绘制34次饼图,模拟3D厚度        ax_pie.pie(data,  #数据                   colors=palette,  #颜色                   explode=explode,  #分裂属性                   startangle=start_angle,  #起始角度                   radius=1.0,  #半径                   counterclock=False,  #顺时针绘制                   center=(0, -i * thickness_factor),  #向下移动中心点以模拟厚度堆叠                   wedgeprops={'alpha': 1, 'edgecolor': 'none'})  #不透明且无边框    _, _, autotexts = ax_pie.pie(data,  #绘制最顶层的饼图                                 colors=palette,  #颜色                                 explode=explode,  #分裂属性                                 startangle=start_angle,  #起始角度                                 autopct='%1.1f%%',  #百分比显示格式                                 pctdistance=0.7,  #百分比标签距离圆心的距离                                 counterclock=False,  #顺时针绘制                                 radius=1.0,  #半径                                 wedgeprops={'linewidth': 2.5, 'edgecolor': 'white'})  #扇形边缘为白色细线    for text in autotexts:        text.set_fontsize(18)  #设置所有百分比文本的字体大小    # 创建一个矩形对象作为外框    rect = Rectangle((-1.25, -1.8),  #左下角坐标                     2.4,  #宽度                     3.5,  #高度                     fill=False,  #不填充颜色                     edgecolor='black',  #边框颜色                     linewidth=2,  #边框线宽                     transform=ax_pie.transData,  #坐标系                     clip_on=False)  #允许矩形超出坐标轴边界显示    ax_pie.add_patch(rect)  #将矩形添加到饼图坐标轴中    #设置标题文本    ax_pie.text(-1.2,  # X坐标                2.45 * aspect_ratio,  #Y坐标(                title,  #内容                fontweight='bold',  #字体加粗                fontsize=20,  #字体大小                transform=ax_pie.transData)  #坐标系    ax_pie.set_aspect(aspect_ratio)  #应用纵横比设置    ax_pie.axis('off')  #隐藏刻度和边框

第四部分

主绘图函数的定义,画布的设置,顶上标题的绘制以最外围的图框的绘制部分
# =========================================================================================# ====================================== 4. 主图绘制函数 =========================================# =========================================================================================def plot_analysis_by_scheme(scheme_id):    current_colors = COLOR_SCHEMES[scheme_id]  #获取颜色方案    fig = plt.figure(figsize=(24, 20), dpi=120)  # 创建画布    a_left, a_right = 0.02, 0.70  #区域A(左侧)的左右边界位置比例    b_left, b_right = 0.71, 0.98  #区域B(右侧)的左右边界位置比例    title_h = 0.045  #标题栏的高度比例    top_y = 1.05  #顶部的Y坐标基准    # 设置左侧大标题的X坐标(居中)    fig.text((a_left + a_right) / 2,  #X坐标             top_y + title_h / 2,  #Y坐标             "(A) Global & TOP 10 countries",  #内容             ha='center',  #水平居中             va='center',  #垂直居中             fontsize=30,  #字体大小             fontweight='bold',  #字体加粗             )    # 设置右侧大标题的X坐标    fig.text((b_left + b_right) / 2,  #X坐标             top_y + title_h / 2,  #Y坐标             "(B) Sectors",  #标题文本             ha='center',  #水平对齐             va='center',  #垂直对齐             fontsize=30,  #字体大小             fontweight='bold',  #加粗             )    #创建大外框矩形    main_border = Rectangle((a_left, 0.01),                            b_right - a_left,  #宽度                            top_y + title_h - 0.05,  #高度                            transform=fig.transFigure,  #使用图形坐标系                            fill=False,  #不填充                            edgecolor='black',  #黑色边框                            linewidth=4,  #线宽                            zorder=10)    fig.patches.append(main_border)  #添加外框到图形

第五部分

创建整体的网格布局,百分比堆叠图的绘制集内嵌饼图的绘制
    # 创建网格布局    gs = gridspec.GridSpec(4,  #行                           3,  #列                           figure=fig,  #归属于当前figure                           width_ratios=[1, 1, 0.8],  #列宽比例                           left=0.07,  #左边距                           right=0.975,  #右边距                           bottom=0.06,  #下边距                           top=top_y - 0.035,  #上边距                           wspace=0.15,  #子图水平间距                           hspace=0.15)  #子图垂直间距    years = [1990, 1995, 2000, 2005, 2010, 2015, 2020]  #分析的年份列表    for i, year in enumerate(years):  #遍历每一年份进行绘图        row, col = divmod(i, 2)  #计算当前年份对应的网格行和列索引        ax = fig.add_subplot(gs[row, col])  #在指定网格位置添加子图        df = df_stacked[df_stacked['Year'] == year].sort_values('Total')  #筛选当年数据并按总值排序        for s_idx, s in enumerate(sectors):            # 绘制水平条形图            ax.barh(df['Country'],  #Y轴                    df[s],  # X轴                    left=left_vals,  #条形的起始位置                    color=current_colors[s_idx],  #颜色                    height=0.7)  #条形高度            left_vals += df[s]  #更新左侧位置,为下一层堆叠做准备        current_max = df['Total'].max()  #获取当前数据的最大总值        ax.set_xlim(0, current_max * 1.3)  #设置X轴范围         #设置子图标题        ax.set_title(f"({chr(97 + i)}) {year}",  #自动生成a, b, c序号                     loc='left',  #左对齐                     fontsize=26,  #字体大小                     fontweight='bold',  #加粗                     pad=8)  #标题与图表的间距        ax.spines[['top', 'right']].set_visible(False)  #隐藏顶部和右侧的边框轴        ax.tick_params(direction='in',  #刻度线向内                       labelsize=24)  #刻度标签字体大小        ax.set_xlabel('(Mt)',  #X轴标签                      loc='right',  #右                      fontsize=24)  #字体大小        for spine in ax.spines.values():  # 遍历所有边框轴            spine.set_linewidth(3)  #设置边框线        draw_3d_pie(ax, global_shares, current_colors)  #调用函数在当前子图中绘制3D饼图

第六部分

箱线图和散点图的组合图的绘制
    #在原有网格的第3列中创建嵌套网格    gs_right = gridspec.GridSpecFromSubplotSpec(5,  #行                                                1,  #列                                                subplot_spec=gs[:, 2],  #指定放置在gs的第3列所有行区域                                                hspace=0.35)  #垂直间距    #遍历绘制右侧图表    for i, sector_name inenumerate(sectors):        ax_b = fig.add_subplot(gs_right[i])  #添加子图到右侧嵌套网格        target_years = [1990, 2000, 2010, 2020]  #定义右侧图表显示的特定年份        color_b = current_colors[i]  #颜色        ax_b.set_title(sector_name,  #子图标题                       loc='right',  #右对齐                       fontsize=26,  #字体大小                       pad=12)  #间距        sector_data = df_scatter[df_scatter['Sector'] == sector_name]  #筛选数据        for j, yr inenumerate(target_years):  #遍历特定年份绘制箱型图元素            vals = sector_data[sector_data['Year'] == yr]['Value'].values  #获取当年数值            iflen(vals) == 0: continue  #如果无数据则跳过            q1, median, q3 = np.percentile(vals, [25, 50, 75])  #计算四分位数和中位数            low, high = np.min(vals), np.max(vals)  #获取最小值和最大值            box_w = 2.5  #设置箱体的一半宽度            rect = Rectangle((yr - box_w, q1),  #创建箱体矩形                             box_w,  #宽度                             q3 - q1,  #高度                             facecolor='none',  #无填充颜色                             edgecolor=color_b,  #边框颜色                             lw=3)  #线宽            ax_b.plot(                [yr, yr],  #上须竖线X坐标                [q3, high],  #上须竖线Y坐标                color=color_b,  #颜色                lw=3)  #线宽            ax_b.plot(                [yr - box_w, yr],  #最大值横线X坐标                      [high, high],  #最大值横线Y坐标                      color=color_b,  #颜色                      lw=3)  #线宽            ax_b.plot(                [yr, yr],  # 下须竖线X坐标                      [q1, low],  #下须竖线Y坐标                      color=color_b,  #颜色                      lw=3)  #线宽            ax_b.plot(                [yr - box_w, yr],  #最小值横线X坐标                      [low, low],  #最小值横线Y坐标                      color=color_b,  #颜色                      lw=3)  #线宽            for spine in ax_b.spines.values():  #遍历边框                spine.set_linewidth(3)  #设置边框线宽            x_jitter = yr + np.random.uniform(1,  #生成散点图的X轴随机抖动                                              1.5,  #抖动范围                                              size=len(vals))  #数量            ax_b.scatter(x_jitter,  #散点图X坐标                         vals,  #Y坐标                         s=14,  #点的大小                         color=color_b,  #颜色                         marker='x',  #标记形状                         alpha=0.8,  #透明度                         lw=3)  #线宽            ax_b.scatter(yr,  #均值点X坐标                         np.mean(vals),  #均值点Y坐标                         color='black',  #颜色                         s=25,  #点的大小                         zorder=5)        ax_b.set_xticks(target_years)  #设置X轴刻度        ax_b.yaxis.set_major_formatter(plt.FuncFormatter(lambda y, _: f'{y:.0%}'))  #设置Y轴标签格式        ax_b.tick_params(direction='in',  #刻度向内                         labelsize=24)  #刻度字体大小

第七部分

虚线分隔线的绘制,图例的绘制,绘图结果保存
    #分隔线    ax_sep = plt.Line2D([b_left - 0.005, b_left - 0.005],  #设置X坐标                        [0.01, top_y + title_h - 0.05],  #Y坐标                        transform=fig.transFigure,  #使用图形坐标系                        color='black',  #黑色                        linestyle='--',  #样式                        linewidth=4,  #线宽                        zorder=11)    fig.lines.append(ax_sep)  #添加线条到图形    fig.legend(handles,  #图例句柄               sectors,  #图例文本               loc='upper left',  #图例位置               bbox_to_anchor=(0.38, 0.28),  #位置               ncol=1,  #列数               frameon=False,  #不显示图例边框               fontsize=36,  #字体大小               title="Legend",  #图例标题               title_fontproperties={'weight': 'bold', 'size': 42},#图例标题属性               alignment='left')  #图例标题相对位置    #保存    save_png_path = r"plot_scheme_{}.png".format(scheme_id)    save_pdf_path = r"plot_scheme_{}.pdf".format(scheme_id)    plt.savefig(save_png_path, dpi=300, bbox_inches='tight')    plt.savefig(save_pdf_path, bbox_inches='tight')

第八部分

执行部分
# =========================================================================================# ======================================5.执行部分=========================================# =========================================================================================if __name__ == "__main__":    file_path = r"data.xlsx"  #文件路径    df_stacked = pd.read_excel(file_path, sheet_name='StackedBarData')  #读取堆叠柱状图数据    df_scatter = pd.read_excel(file_path, sheet_name='SectorDistribution')  #读取散点图数据    sectors = ['Power Industry', 'Building', 'Transport', 'Other Industrial Combustion', 'Other Sectors']  # 定义分区    scheme_index = 20 #颜色方案ID    plot_analysis_by_scheme(scheme_index)  #调用主绘图函数

如何应用到你自己的数据

1.设置原始数据文件的路径:

file_path = r"data.xlsx"  #文件路径

2.设置要读取的指定表的数据:

df_stacked = pd.read_excel(file_path, sheet_name='StackedBarData')df_scatter = pd.read_excel(file_path, sheet_name='SectorDistribution')

3.设置分区:

sectors = ['Power Industry', 'Building', 'Transport', 'Other Industrial Combustion', 'Other Sectors']

4.设置颜色方案:

scheme_index = 20 #选择颜色方案ID

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

save_png_path = r"plot_scheme_{}.png".format(scheme_id)save_pdf_path = r"plot_scheme_{}.pdf".format(scheme_id)

推荐

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

获取方式

需要的请后台私信我,注意只会分享练习数据和代码文件,不会提供答疑服务,代码文件中已经包含了每行代码的完整注释!!!

最新文章

随机文章