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

Matplotlib三元图报错:'AxesSubplot'对象无'colorbar'属性

错误原因与修复方案:AttributeError: 'AxesSubplot' object has no attribute 'colorbar'

错误根源

你的代码中创建画布对象时出现了关键错误:

fig = plt.subplot()
ax = plt.subplot()

plt.subplot()返回的是坐标轴对象(AxesSubplot),而非Matplotlib的画布对象(Figure)。而colorbar是Figure对象独有的方法,当你把这个错误的"fig"传入plot2方法调用fig.colorbar()时,自然会触发AttributeError。

修复步骤

1. 正确创建Figure和Axes对象

将创建画布和坐标轴的代码替换为:

fig, ax = plt.subplots(figsize=(10, 10))  # figsize可根据需求调整,适配三元图比例

这行代码会同时返回正确的Figure对象(fig)和对应的坐标轴对象(ax)。

2. 可选优化(提升图表效果)

  • 修复数据追加逻辑:append_data方法开头的清空语句会导致多次添加数据时丢失之前的内容,建议移除:
    # 移除append_data方法中的这三行
    self.weights = []
    self.colors = []
    self.labels = []
    
  • 调整坐标轴范围:三元图是等边三角形,实际高度为√3/2≈0.866,修改plot_frame中的坐标轴范围,减少顶部空白:
    # 替换原ax.axis(...)
    ax.axis([-0.1, 1.1, -0.025, 0.9])
    

完整修正后的代码

import matplotlib.pyplot as plt
from matplotlib.colors import LogNorm
import matplotlib.cm as cm
import numpy as np
import matplotlib as mpl
import pandas as pd
from math import sqrt
from matplotlib.ticker import LogFormatter
from mpl_toolkits.axes_grid1 import make_axes_locatable

dataset = pd.read_excel('/content/Sequecia BC74 teste v2.xlsx')

class Ternary:
    font_size = 12
    plot_size = 12

    def __init__(self, label_A: str = "A", label_B: str = "B", label_C: str = "C",
                 min_ternary: float = 0):
        self.label_A = label_A
        self.label_B = label_B
        self.label_C = label_C
        self.min_ternary = min_ternary
        self.weights = []
        self.colors = []
        self.labels = []
        self.X = []
        self.Y = []
        self.Z = []

    def append_data(self, A, B, C, weights=None, colors=None, tick_label: list=[]):
        # 移除原清空语句,支持多次追加数据
        if len(A) != len(B) or len(B) != len(C):
            print("ERROR in append_data, table length are different")
        else:
            for i in range(len(A)):
                if A[i] + B[i] + C[i] >= self.min_ternary:
                    self.X.append(0.5 * (2 * C[i] + B[i]) / (A[i] + B[i] + C[i]))
                    self.Y.append(sqrt(3) * 0.5 * B[i] / (A[i] + B[i] + C[i]))
                    if weights is not None:
                        self.weights.append(weights[i])
                    else:
                        self.weights.append(1)
                    if colors is not None:
                        self.colors.append(colors[i])
                    else:
                        self.colors.append(1)
                    if len(tick_label) > 0:
                        self.labels.append(tick_label[i])

    def plot2(self, ax, fig, cmap, norm, bounds, scale_factor: int = 1, weight_label: str = None, color_label: str = None,
              label: str = "Ter", tet_marks: bool = False, graduation_step: float = 10,  show_scale: bool = True, 
              show_legend: bool = True):
        self.plot_frame(ax=ax, graduation_step=graduation_step, tetrahedron_marks=tet_marks)
        # Label
        label_points = label + " - " + str(len(self.X)) + " inclusions"
        if weight_label is not None:
            label_mean = "Mean " + weight_label + ": " + str(np.round(np.mean(np.asarray(self.weights)), 2))
        else:
            label_mean = "Mean"
        if color_label is not None:
            label_mean += " / color coding: " + color_label
        # Plot data
        if len(self.labels) > 0:
            if len(np.unique(np.asarray(self.labels))) > 10:
                cmap = cm.tab20
            else:
                cmap = cm.tab10
            unique, index, inverse = np.unique(self.colors, return_index=True, return_inverse=True)
            self.colors = inverse
            bounds = range(len(np.unique(np.asarray(self.labels)[index])))
        dat = ax.scatter(self.X, self.Y, s=[x * scale_factor for x in self.weights], label=label_points, c=self.colors,
                         cmap=cmap, norm=norm, edgecolors="k", linewidth=0.25)
        divider = make_axes_locatable(ax)
        cax = divider.append_axes('right', size='5%', pad=0.05)
        cbar = fig.colorbar(dat, cax=cax, format='%.2f', ticks=bounds)
        cbar.ax.tick_params(labelsize=12)
        if len(self.labels) > 0:
            cbar.ax.set_yticklabels(np.asarray(self.labels)[index])
        # Plot Mean
        ax.scatter(np.mean(np.asarray(self.X)), np.mean(np.asarray(self.Y)),
                   s=scale_factor * np.mean(self.weights), label=label_mean, edgecolors="k", linewidth=0.25,
                   color="black")
        ax.legend(fontsize="large", loc="upper right")
        return dat


    def plot_frame(self, ax, graduation_step: float = 10, tetrahedron_marks: bool = False):
        T1 = [0, 0.5]
        TT1 = [x * sqrt(3) for x in T1]
        T2 = [0.5, 1]
        TT2 = [(-x * (sqrt(3))) + sqrt(3) for x in T2]
        T3 = [0, 1]
        TT3 = [0 * x for x in T3]
        ax.plot(T1, TT1, c='black', lw=0.5)
        ax.plot(T2, TT2, c='black', lw=0.5)
        ax.plot(T3, TT3, c='black', lw=0.5)
        for x in np.linspace(graduation_step, 100 - graduation_step, int((100 / graduation_step) - 1)):
            x = x/100
            T = [x, x + 0.5 * (1 - x)]
            TT = [sqrt(3) * (y - x) for y in T]
            ax.plot(T, TT, c='grey', lw=0.2)
            T = [0.5 * x, 1 - 0.5 * x]
            TT = [sqrt(3) * 0.5 * x for y in T]
            ax.plot(T, TT, c='grey', lw=0.2)
            T = [(1 - x) * 0.5, 1 - x]
            TT = [-sqrt(3) * y + sqrt(3) * (1 - x) for y in T]
            ax.plot(T, TT, c='grey', lw=0.2)
        # 调整坐标轴范围,适配等边三角形高度
        ax.axis([-0.1, 1.1, -0.025, 0.9])
        ax.text(-0.05, 0, self.label_A, fontsize=self.font_size)
        ax.text(0.5, (0.5 * sqrt(3)) * (1 + 0.02), self.label_B, fontsize=self.font_size)
        ax.text(1 + 0.02, 0, self.label_C, fontsize=self.font_size)
        if tetrahedron_marks:
            T1 = [0, 0.5]
            TT1 = [x * 2 * sqrt(1 / 12) for x in T1]
            T2 = [0.5, 1]
            TT2 = [(-x * 2 * sqrt(1 / 12) + 2 * sqrt(1 / 12)) for x in T2]
            T3 = [0.5, 0.5]
            TT3 = [sqrt(1 / 12), sqrt(3) / 2]
            ax.plot(T1, TT1, c='black', lw=0.5)
            ax.plot(T2, TT2, c='black', lw=0.5)
            ax.plot(T3, TT3, c='black', lw=0.5)
        ax.set_aspect(aspect="equal")
        ax.axis("off")

ter = Ternary()    
ter.append_data(dataset['CaOMnOMgO'], dataset['SiO2'], dataset['Al2O3'],dataset['Tamanho'],dataset['O2'])
# 正确创建Figure和Axes对象
fig, ax = plt.subplots(figsize=(10,10))
cmap = mpl.cm.coolwarm
bounds = [1, 2, 3, 4, 5, 10]
norm = mpl.colors.BoundaryNorm(bounds, cmap.N)
ter.plot2(ax, fig, cmap, norm, bounds)
plt.show()  # 添加这行确保图表显示

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 11:50:31