期刊复现|Python 实现带误差棒与3D 柱状数据可视化

论文地址:

https://www.sciencedirect.com/science/article/pii/S0023643823010538

论文题目:

Sensory profile and the contribution of key aroma compounds in Jiang-flavor rounded-base Baijiu produced in the Chishui river basin

复现图片:

图 1 3D 柱状图:该图直观呈现多组样本的物种数量差异。横坐标为样本类型,纵坐标为分组类别,竖轴表示物种数量,不同颜色对应不同组别,误差棒展示数据波动范围,柱形顶端标注具体数值。正式图注:图 1 多组样本物种数量分布 3D 柱状图

配色方案:

python 复制代码
COLOR_SCHEMES = {
    1: ['#0055D4', '#00C4FF', '#A3D8FF', '#E6E6E6', '#FFB78C', '#FF7F50', '#D62728'],
    2: ['#8C510A', '#D8B365', '#F6E8C3', '#F5F5F5', '#C7EAE5', '#5AB4AC', '#01665E'],
    3: ['#B2182B', '#EF8A62', '#FDDBC7', '#F7F7F7', '#D1E5F0', '#67A9CF', '#2166AC'],
    4: ['#762A83', '#AF8DC3', '#E7D4E8', '#F7F7F7', '#D9F0D3', '#7FBF7B', '#1B7837'],
    5: ['#B35806', '#F1A340', '#FEE0B6', '#F7F7F7', '#D8DAEB', '#998EC3', '#542788'],
    6: ['#C51B7D', '#E9A3C9', '#FDE0EF', '#F7F7F7', '#E6F5D0', '#A1D76A', '#4D9221'],
    7: ['#D73027', '#FC8D59', '#FEE090', '#FFFFBF', '#E0F3F8', '#91BFDB', '#4575B4'],
    8: ['#006837', '#31A354', '#78C679', '#C2E699', '#FFFFCC', '#FFEDA0', '#FEB24C'],
    9: ['#08589E', '#2B8CBE', '#4EB3D3', '#7BCCC4', '#A8DDB5', '#CCEBC5', '#F0F9E8'],
    10: ['#990000', '#D7301F', '#EF6548', '#FC8D59', '#FDBB84', '#FDD49E', '#FEF0D9'],
    11: ['#3F007D', '#54278F', '#6A51A3', '#807DBA', '#9E9AC8', '#BCBDDC', '#DADAEB'],
    12: ['#000000', '#252525', '#525252', '#737373', '#969696', '#BDBDBD', '#D9D9D9'],
    13: ['#49006A', '#7A0177', '#AE017E', '#DD3497', '#F768A1', '#FA9FB5', '#FCC5C0'],
    14: ['#084081', '#0868AC', '#2B8CBE', '#4EB3D3', '#7BCCC4', '#A8DDB5', '#CCEBC5'],
    15: ['#8C2D04', '#CC4C02', '#EC7014', '#FE9929', '#FEC44F', '#FEE391', '#FFFFD4'],
    16: ['#E4572E', '#29335C', '#F3A712', '#A8C686', '#669BBC', '#E09F3E', '#9E2A2B'],
    17: ['#FF007F', '#00F0FF', '#FFEA00', '#8A2BE2', '#00FF7F', '#FF4500', '#191970'],
    18: ['#5E81AC', '#81A1C1', '#88C0D0', '#8FBCBB', '#BF616A', '#D08770', '#EBCB8B'],
    19: ['#FF3B30', '#FF9500', '#FFCC00', '#4CD964', '#5AC8FA', '#007AFF', '#5856D6'],
    20: ['#4A2511', '#8C3A00', '#D96C06', '#F2A007', '#F2D06B', '#A69E8D', '#59604C'],
    21: ['#FFB3BA', '#FFDFBA', '#FFFFBA', '#BAFFC9', '#BAE1FF', '#D3B1FF', '#FFB1E6'],
    22: ['#1A1A1D', '#4E4E50', '#6F2232', '#950740', '#C3073F', '#F0A07C', '#F2E8CF'],
    23: ['#05668D', '#028090', '#00A896', '#02C39A', '#F0F3BD', '#FFB563', '#FF8166'],
    24: ['#332E28', '#66594C', '#998675', '#CCBAA3', '#F2E6D8', '#40593A', '#8C2E2E'],
    25: ['#FDF500', '#00FF41', '#008F11', '#00B8FF', '#FF003C', '#D400FF', '#2700FF'],
    26: ['#264653', '#2A9D8F', '#E9C46A', '#F4A261', '#E76F51', '#8AB17D', '#B23A48'],
    27: ['#D9ED92', '#B5E48C', '#99D98C', '#76C893', '#168AAD', '#1A759F', '#184E77'],
    28: ['#001219', '#005F73', '#0A9396', '#94D2BD', '#E9D8A6', '#EE9B00', '#CA6702'],
    29: ['#FF595E', '#FFCA3A', '#8AC926', '#1982C4', '#6A4C93', '#F4A261', '#E76F51'],
    30: ['#22223B', '#4A4E69', '#9A8C98', '#C9ADA7', '#F2E9E4', '#D4A373', '#FAEDCD'],
    31: ['#FF9F1C', '#FFBF69', '#FFFFFF', '#CBF3F0', '#2EC4B6', '#E71D36', '#011627'],
    32: ['#000000', '#14213D', '#FCA311', '#E5E5E5', '#FFFFFF', '#D90429', '#EF233C'],
    33: ['#8ECAE6', '#219EBC', '#023047', '#FFB703', '#FB8500', '#8A817C', '#463F3A'],
    34: ['#CCD5AE', '#E9EDC9', '#FEFAE0', '#FAEDCD', '#D4A373', '#606C38', '#283618'],
    35: ['#03045E', '#0077B6', '#00B4D8', '#90E0EF', '#CAF0F8', '#FFB703', '#FB8500'],
    36: ['#0B090A', '#161A1D', '#660708', '#A4161A', '#BA1826', '#E5383B', '#F5F3F4'],
    37: ['#F94144', '#F3722C', '#F8961E', '#F9C74F', '#90BE6D', '#43AA8B', '#577590'],
    38: ['#540D6E', '#EE4266', '#FFD23F', '#3BCEAC', '#0EAD69', '#118AB2', '#073B4C'],
    39: ['#10002B', '#240046', '#3C096C', '#5A189A', '#7B2CBF', '#9D4EDD', '#C77DFF'],
    40: ['#E63946', '#F1FAEE', '#A8DADC', '#457B9D', '#1D3557', '#F4A261', '#E76F51'],
    41: ['#003049', '#D62828', '#F77F00', '#FCBF49', '#EAE2B7', '#7F4F24', '#582F0E'],
    42: ['#2B2D42', '#8D99AE', '#EDF2F4', '#EF233C', '#D90429', '#6D6875', '#B5838D'],
    43: ['#780000', '#C1121F', '#FDF0D5', '#003049', '#669BBC', '#4A4E69', '#22223B'],
    44: ['#355070', '#6D597A', '#B56576', '#E56B6F', '#EAAC8B', '#FFB4A2', '#FFCDB2'],
    45: ['#F72585', '#7209B7', '#3A0CA3', '#4361EE', '#4CC9F0', '#00F5D4', '#9D4EDD'],
    46: ['#FFCDB2', '#FFB4A2', '#E5989B', '#B5838D', '#6D6875', '#355070', '#1D3557'],
    47: ['#2F3E46', '#354F52', '#52796F', '#84A98C', '#CAD2C5', '#F2E9E4', '#C9ADA7'],
    48: ['#112A46', '#1A4301', '#247B7B', '#78A1BB', '#BFE2C7', '#EFCB68', '#AE3131'],
    49: ['#001524', '#15616D', '#FFECD1', '#FF7D00', '#78290F', '#B39BC8', '#F1D8C1'],
    50: ['#386641', '#6A994E', '#A7C957', '#F2E8CF', '#BC4749', '#3D348B', '#7678ED'],
    51: ['#F9A03F', '#F7D002', '#F2ED6F', '#CFE0C3', '#9EC1A3', '#70A9A1', '#40798C'],
    52: ['#390099', '#9E0059', '#FF0054', '#FF5400', '#FFBD00', '#3A0CA3', '#4CC9F0'],
    53: ['#CDB4DB', '#FFC8DD', '#FFAFCC', '#BDE0FE', '#A2D2FF', '#83C5BE', '#006D77'],
    54: ['#ED6A5A', '#F4F1DE', '#F2CC8F', '#E07A5F', '#3D405B', '#81B29A', '#7A9E9F'],
    55: ['#0D3B66', '#FAF0CA', '#F4D35E', '#EE964B', '#F95738', '#8B2635', '#482C3D'],
    56: ['#0F4C5C', '#E5989B', '#B5838D', '#6D6875', '#B8B8FF', '#9381FF', '#F8F7FF'],
    57: ['#3A5A40', '#588157', '#A3B18A', '#DAD7CD', '#D4A373', '#FAEDCD', '#FEFAE0'],
    58: ['#0466C8', '#0353A4', '#023E8A', '#002855', '#001845', '#001233', '#33415C'],
    59: ['#283618', '#606C38', '#DDA15E', '#BC6C25', '#FEFAE0', '#E9EDC9', '#CCD5AE'],
    60: ['#E29578', '#FFDDD2', '#EDF6F9', '#83C5BE', '#006D77', '#003049', '#D62828']
}

完整代码:

python 复制代码
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import rcParams
import matplotlib.patches as mpatches
import pandas as pd
import matplotlib
import os

matplotlib.rcParams['pdf.fonttype'] = 42
matplotlib.rcParams['ps.fonttype'] = 42
plt.rcParams['font.family'] = 'Times New Roman'
plt.rcParams['font.weight'] = 'bold'
plt.rcParams['axes.labelweight'] = 'bold'
plt.rcParams['axes.titleweight'] = 'bold'

COLOR_SCHEMES = {
    7: ['#D73027', '#FC8D59', '#FEE090', '#FFFFBF', '#E0F3F8', '#91BFDB', '#4575B4'],
}
color_scheme_id = 7
colors = COLOR_SCHEMES[color_scheme_id][::-1]

def plot_formatted_3d_bars(data, error_data, x_labels, y_labels, colors):
    # 自动创建保存文件夹
    save_dir = "图表"
    if not os.path.exists(save_dir):
        os.makedirs(save_dir)

    num_y, num_x = data.shape
    X, Y = np.meshgrid(np.arange(num_x), np.arange(num_y))
    X = X.flatten()
    Y = Y.flatten()
    Z = np.zeros_like(X)

    dx_val = 0.5
    dy_val = 0.65
    dx = dx_val * np.ones_like(X)
    dy = dy_val * np.ones_like(Y)
    dz = data.flatten()

    color_list = []
    for i in range(num_y):
        color_list.extend([colors[i]] * num_x)

    fig = plt.figure(figsize=(14, 8), dpi=150)
    ax = fig.add_subplot(111, projection='3d')
    ax.bar3d(X, Y, Z, dx, dy, dz, color=color_list, alpha=0.9, shade=True)

    for i in range(num_y):
        for j in range(num_x):
            x_pos = j + dx_val / 2
            y_pos = i + dy_val / 2
            z_pos = data[i, j]
            err = error_data[i, j]

            ax.plot([x_pos, x_pos], [y_pos, y_pos], [z_pos, z_pos + err], color='black', linewidth=1, zorder=10)
            cap_width = 0.12
            ax.plot([x_pos - cap_width, x_pos + cap_width], [y_pos, y_pos], [z_pos + err, z_pos + err], color='black', linewidth=1, zorder=10)
            ax.text(x_pos, y_pos, z_pos + err + 1.5, str(int(z_pos)), color='black', ha='center', va='bottom', fontweight='bold', fontsize=10, zorder=10)


    ax.set_xticks(np.arange(num_x) + dx_val / 2)
    ax.set_xticklabels(x_labels, rotation=30, ha='right', va='center', fontsize=12)
    ax.tick_params(axis='x', pad=8)

    ax.set_yticks(np.arange(num_y) + dy_val / 2)
    ax.set_yticklabels(y_labels, fontsize=12)
    ax.tick_params(axis='y', pad=5)

    ax.set_zlabel('Species', fontsize=16, fontweight='bold', labelpad=15)
    ax.grid(False)

    ax.xaxis.pane.fill = False
    ax.yaxis.pane.fill = False
    ax.zaxis.pane.fill = False
    ax.xaxis.pane.set_edgecolor('none')
    ax.yaxis.pane.set_edgecolor('none')
    ax.zaxis.pane.set_edgecolor('none')
    ax.xaxis.line.set_color('black')
    ax.yaxis.line.set_color('black')
    ax.zaxis.line.set_color('black')
    ax.zaxis._axinfo['juggled'] = (1, 2, 2)

    ax.view_init(elev=20, azim=-55)
    ax.set_box_aspect(aspect=(2.5, 1.5, 1))

    legend_patches = [mpatches.Patch(color=colors[i], label=y_labels[i]) for i in range(num_y)]
    ax.legend(handles=legend_patches, loc='upper right', bbox_to_anchor=(0.9, 0.8), frameon=False, fontsize=12)

    plt.subplots_adjust(left=0.05, right=0.85, bottom=0.15, top=0.95)

    # 仅保存PNG
    png_path = os.path.join(save_dir, f'3d_bar_chart{color_scheme_id}.png')
    plt.savefig(png_path, dpi=300, bbox_inches='tight')
    plt.close()

if __name__ == '__main__':
    file_path = "data.xlsx"
    df_data = pd.read_excel(file_path, sheet_name='Mean_Data', index_col=0)
    df_error = pd.read_excel(file_path, sheet_name='Error_Data', index_col=0)

    x_labels = df_data.columns.tolist()
    y_labels = df_data.index.tolist()
    data = df_data.values
    error_data = df_error.values

    plot_formatted_3d_bars(data, error_data, x_labels, y_labels, colors)

数据获取

评论+私信获取

VX获取: 期刊复现|Python 实现带误差棒与3D 柱状数据可视化https://mp.weixin.qq.com/s/X8_xNXiSW9HI23b0bvlkpA

参考来源:python+遥感学习日志

相关推荐
财经资讯数据_灵砚智能1 小时前
基于全球经济类多源新闻的NLP情感分析与数据可视化(夜间-次晨)2026年5月25日
大数据·人工智能·python·信息可视化·自然语言处理·ai编程
是你就无限6151 小时前
FastAPI 核心技术与实战
python·fastapi
是上好佳佳佳呀1 小时前
【Python基础|DAY05】Python 模块与包
python
大数据魔法师1 小时前
Streamlit(十一)- API 参考文档(四)- 图表元素
python·web
AllData公司负责人2 小时前
亲测丝滑,体验跃迁|AllData通过集成开源项目Datart,让数据可视化一目了然
java·大数据·数据库·python·数据可视化·数据视图·datart
tang777892 小时前
2026代理IP选型逻辑与成本控制:动态IP VS 静态IP、住宅IP VS 运营商IP VS 数据中心IP的深入解析
爬虫·python·代理ip·住宅ip·住宅代理·运营商ip
AI玫瑰助手2 小时前
Python函数:def定义函数与参数传递基础
android·开发语言·python
24kmaigc2 小时前
NewStarCTF2025-ssti在哪里?-ssrf与ssti注入
python·网络安全·flask·web
老虎海子2 小时前
从零手搓一个 AI 编程助手:Mini Claude Code 完全指南
人工智能·git·vscode·python·github