论文地址:
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+遥感学习日志