You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:基于Pandas列调整Matplotlib箱线图样式(颜色、图例、X轴)

问题需求

我需要将当前的Matplotlib箱线图修改为指定样式,具体要求如下:

  • 按Oxidation列的类别设置箱线颜色:oxide为红色,transition为绿色,fresh为蓝色;
  • 添加对应类别的图例;
  • 简化X轴,仅显示元素名称。

以下是数据片段、当前使用的Matplotlib脚本,以及我尝试的Seaborn脚本(但无法自定义分位数和轴样式),恳请协助解决:

数据片段

Oxidation   Elements    GAI
1.OXIDE Ag_ppm  1
2.TRANS Ag_ppm  1
2.TRANS Ag_ppm  0
2.TRANS Ag_ppm  2
2.TRANS Ag_ppm  2
2.TRANS Ag_ppm  1
3.FRESH Ag_ppm  2
3.FRESH Ag_ppm  0
3.FRESH Ag_ppm  0
3.FRESH Ag_ppm  1
3.FRESH Ag_ppm  0
3.FRESH Ag_ppm  0
1.OXIDE Ag_ppm  0
1.OXIDE Ag_ppm  1
1.OXIDE Ag_ppm  0
1.OXIDE Ag_ppm  0
1.OXIDE Ag_ppm  0
1.OXIDE Ag_ppm  0
1.OXIDE Cu_ppm  1
2.TRANS Cu_ppm  1
2.TRANS Cu_ppm  1
2.TRANS Cu_ppm  1
2.TRANS Cu_ppm  2
2.TRANS Cu_ppm  1
3.FRESH Cu_ppm  2
3.FRESH Cu_ppm  1
3.FRESH Cu_ppm  2
3.FRESH Cu_ppm  2
3.FRESH Cu_ppm  2
3.FRESH Cu_ppm  1
3.FRESH Cu_ppm  2
1.OXIDE Cu_ppm  3
1.OXIDE Cu_ppm  3
1.OXIDE Cu_ppm  3
1.OXIDE Cu_ppm  4
1.OXIDE Cu_ppm  2
1.OXIDE Mg_pct  1
1.OXIDE Mg_pct  1
1.OXIDE Mg_pct  3
1.OXIDE Mg_pct  2
1.OXIDE Mg_pct  1
1.OXIDE Mg_pct  1
1.OXIDE Mg_pct  2
1.OXIDE Mg_pct  2
2.TRANS Mg_pct  2
2.TRANS Mg_pct  2
2.TRANS Mg_pct  2
2.TRANS Mg_pct  2
2.TRANS Mg_pct  2
3.FRESH Mg_pct  2
3.FRESH Mg_pct  2
3.FRESH Mg_pct  2
3.FRESH Mg_pct  2
3.FRESH Mg_pct  2

当前Matplotlib脚本

# Plot boxplots
fig, ax = plt.subplots(figsize = (20,8))

# Box plot properties
mean = dict(marker = 'x', mec = 'Black', ms = 9)
median=dict(color ="Black", lw=1.2)
whisker=dict(color ="Black", lw=1.2)
cap=dict(color ="Black", lw=1.2)
flier=dict(markerfacecolor= 'green', ms=10)

key_label = ['Ag','Cu','Mg']
key_ox = ['Oxide','Transition','Fresh','Oxide','Transition','Fresh','Oxide','Transition','Fresh']
col_ox = ['r','g','b','r','g','b','r','g','b']

gai_waste.boxplot(ax=ax, by = ['Elements', 'Oxidation'], column =["GAI"],
                  color = '#ADD8E6', patch_artist=True, whis=[10, 90], #widths=0.2,
                  whiskerprops = whisker, showmeans=True, meanprops = mean, medianprops=median, capprops = cap, showfliers=False,
                  grid = True, rot = 90, fontsize = 'medium')

plt.ylabel("GAI", fontsize = 'x-large', fontname='Calibri', weight='bold')
plt.xlabel(None)
plt.yticks(fontsize = 'large', fontname='Calibri')
plt.xticks(np.arange(1, 10, 1),labels=key_ox,ha='center',fontsize = 'large', fontname='Calibri', rotation = 0)
ax.yaxis.set_major_formatter(FormatStrFormatter('%.0f'))
plt.grid(True, which='both', color='lightgrey',ls = '--')
plt.suptitle('')
plt.title('')

x=2
for i in range(3):
    plt.text(x = x , y = -5.5, s = str(key_label[i]),horizontalalignment='center', fontsize = 'x-large', weight='bold')
    x+=3

尝试的Seaborn脚本

fig, ax = plt.subplots(figsize = (20,8))

sns.set_theme(style="ticks", palette="pastel")

sns.boxplot(data=gai_waste, x='Elements', y='GAI', hue='Oxidation', palette=['r','g','b'],
            width=0.5, dodge=True, ax=ax, whis=[10,90], showfliers=False , whiskerprops = whisker, medianprops=median,
            showmeans=True,meanprops=mean)
sns.despine(offset=10, trim=True)
plt.xlabel(None)

#add legend image
img = plt.imread("legend2.jpg")
ab = AnnotationBbox(OffsetImage(img, zoom=0.1), (5,-2.5), frameon=True)
ax.add_artist(ab)

解决方案

方案1:改进Matplotlib原生脚本

直接基于现有代码修改,完全满足三个需求:

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.ticker import FormatStrFormatter
from matplotlib.patches import Patch

# 定义颜色与标签映射
color_map = {"1.OXIDE": "red", "2.TRANS": "green", "3.FRESH": "blue"}
label_map = {"1.OXIDE": "Oxide", "2.TRANS": "Transition", "3.FRESH": "Fresh"}

fig, ax = plt.subplots(figsize=(20, 8))

# 箱线图样式参数
mean_props = dict(marker='x', mec='Black', ms=9)
median_props = dict(color="Black", lw=1.2)
whisker_props = dict(color="Black", lw=1.2)
cap_props = dict(color="Black", lw=1.2)

# 生成箱线图
box = gai_waste.boxplot(
    ax=ax, by=['Elements', 'Oxidation'], column=["GAI"],
    patch_artist=True, whis=[10, 90],
    whiskerprops=whisker_props, showmeans=True, meanprops=mean_props,
    medianprops=median_props, capprops=cap_props, showfliers=False,
    grid=True, fontsize='medium'
)

# 按类别设置箱线颜色
groups = gai_waste.groupby(['Elements', 'Oxidation']).size().index
for patch, (_, ox) in zip(box['boxes'], groups):
    patch.set_facecolor(color_map[ox])

# 添加自定义图例
legend_elements = [
    Patch(facecolor=color_map["1.OXIDE"], label=label_map["1.OXIDE"]),
    Patch(facecolor=color_map["2.TRANS"], label=label_map["2.TRANS"]),
    Patch(facecolor=color_map["3.FRESH"], label=label_map["3.FRESH"])
]
ax.legend(handles=legend_elements, loc='upper right', fontsize='large')

# 简化X轴:仅显示元素名称
ax.set_xticklabels([])
# 每个元素组的中心位置:2、5、8
element_positions = [2, 5, 8]
element_names = ['Ag', 'Cu', 'Mg']
for elem, pos in zip(element_names, element_positions):
    ax.text(pos, -0.3, elem, horizontalalignment='center',
            fontsize='x-large', weight='bold', transform=ax.get_xaxis_transform())

# 其他样式调整
plt.ylabel("GAI", fontsize='x-large', fontname='Calibri', weight='bold')
plt.xlabel(None)
plt.yticks(fontsize='large', fontname='Calibri')
ax.yaxis.set_major_formatter(FormatStrFormatter('%.0f'))
plt.grid(True, which='both', color='lightgrey', ls='--')
plt.suptitle('')
plt.title('')

plt.tight_layout()
plt.show()

方案2:修正Seaborn脚本实现需求

Seaborn支持自定义分位数和轴样式,之前的问题是图例处理不当,修改后代码如下:

import matplotlib.pyplot as plt
import seaborn as sns
from matplotlib.ticker import FormatStrFormatter

# 颜色与标签映射
color_palette = {"1.OXIDE": "red", "2.TRANS": "green", "3.FRESH": "blue"}
label_map = {"1.OXIDE": "Oxide", "2.TRANS": "Transition", "3.FRESH": "Fresh"}

fig, ax = plt.subplots(figsize=(20, 8))

# 设置Seaborn基础样式
sns.set_theme(style="ticks")

# 绘制箱线图,指定分位数与样式
sns.boxplot(
    data=gai_waste, x='Elements', y='GAI', hue='Oxidation',
    palette=color_palette, width=0.5, dodge=True, ax=ax,
    whis=[10, 90], showfliers=False,
    whiskerprops=dict(color="Black", lw=1.2),
    medianprops=dict(color="Black", lw=1.2),
    showmeans=True, meanprops=dict(marker='x', mec='Black', ms=9)
)

# 简化X轴标签为仅元素名称
ax.set_xticklabels([label.get_text().split('_')[0] for label in ax.get_xticklabels()],
                   fontsize='x-large', weight='bold')

# 修正图例标签
handles, labels = ax.get_legend_handles_labels()
ax.legend(handles=handles, labels=[label_map[l] for l in labels], loc='upper right', fontsize='large')

# 其他样式调整
plt.ylabel("GAI", fontsize='x-large', fontname='Calibri', weight='bold')
plt.xlabel(None)
plt.yticks(fontsize='large', fontname='Calibri')
ax.yaxis.set_major_formatter(FormatStrFormatter('%.0f'))
ax.grid(True, which='both', color='lightgrey', ls='--', axis='y')
sns.despine(offset=10, trim=True)

plt.tight_layout()
plt.show()

内容的提问来源于stack exchange,提问作者BRat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 17:45:53