es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Error de atributo: el objeto ‘BarContainer’ no tiene el atributo ‘get_height’

Necesito dividir el eje y del código “yaxis” del MWE a continuación en el rango [40, 90]:

import numpy as np
import matplotlib.pyplot as plt

n = 2
ind = np.arange(n)
width = 0.45

fig = plt.figure()
ax = fig.add_subplot(111)

yvals = [10, 20]
rects1 = ax.bar(ind, yvals, width, color=’r’)
zvals = [15,35]
rects2 = ax.bar(ind+width, zvals, width, color=’g’)

ax.set_ylim([0, 100])

ax.set_ylabel(‘Y’)
ax.set_xlabel(‘X’)
ax.set_xticks(ind+width/2)

ax.set_xticklabels((‘A’, ‘B’))
ax.legend((rects1[0], rects2[0]), (‘M’, ‘N’))

def autolabel(rects):
for rect in rects:
h = rect.get_height()
ax.text(rect.get_x()+rect.get_width()/2., 1.05*h, ‘{}’.format(int(h)),
ha=’center’, va=’bottom’)

autolabel(rects1)
autolabel(rects2)

plt.show()

Entonces, usando el módulo “Brokenaxes”, intenté lo siguiente:

import numpy as np
import matplotlib.pyplot as plt
from brokenaxes import brokenaxes

N = 2
ind = np.arange(N)
width = 0.45

fig = plt.figure()

baxes = brokenaxes(ylims=((0, 40), (90, 100)), hspace=.05)

yvals = [10, 20]
rects1 = baxes.bar(ind, yvals, width, color=’r’)
zvals = [15, 35]
rects2 = baxes.bar(ind+width, zvals, width, color=’g’)

baxes.set_ylim([0, 100])

baxes.set_ylabel(‘Y’)
baxes.set_xlabel(‘X’)
baxes.set_xticks(ind+width/2)

baxes.set_xticklabels((‘A’, ‘B’))
baxes.legend((rects1[0], rects2[0]), (‘M’, ‘N’))

def autolabel(rects):
for rect in rects:
h = rect.get_height()
baxes.text(rect.get_x()+rect.get_width()/2., 1.05*h, ‘{}’.format(int(h)),
ha=’center’, va=’bottom’)

autolabel(rects1)
autolabel(rects2)

plt.show()

Pero arroja:

AttributeError: El objeto ‘BarContainer’ no tiene el atributo ‘get_height’

¿Cómo se puede resolver este problema?

Tags:  ,

Answer

  1. Avatar for davy.ai

    El problema con el código es que rects en la función autolabel son contenedores de barras y no rectángulos individuales. Por lo tanto, rect.get_height() no es un atributo válido. Para solucionar esto, necesitamos iterar sobre los rectángulos individuales en cada contenedor para obtener sus alturas. Aquí está la función autolabel actualizada:

    def autolabel(rects):
        for rect in rects:
            for r in rect:
                h = r.get_height()
                baxes.text(r.get_x()+r.get_width()/2., 1.05*h, '%{}'.format(int(h)),
                        ha='center', va='bottom')
    

    El código brokenaxes actualizado con la función corregida se muestra a continuación:

    import numpy as np
    import matplotlib.pyplot as plt
    from brokenaxes import brokenaxes
    
    N = 2
    ind = np.arange(N)  
    width = 0.45       
    
    fig = plt.figure()
    
    baxes = brokenaxes(ylims=((0,40),(90,100)), hspace=.05)
    
    yvals = [10, 20]
    rects1 = baxes.bar(ind, yvals, width, color='r')
    zvals = [15, 35]
    rects2 = baxes.bar(ind+width, zvals, width, color='g')
    
    baxes.set_ylim([0, 100])
    
    baxes.set_ylabel('Y')
    baxes.set_xlabel('X')
    baxes.set_xticks(ind+width/2)
    
    baxes.set_xticklabels( ('A', 'B') )
    baxes.legend( (rects1[0], rects2[0]), ('M', 'N') )
    
    def autolabel(rects):
        for rect in rects:
            for r in rect:
                h = r.get_height()
                baxes.text(r.get_x()+r.get_width()/2., 1.05*h, '%{}'.format(int(h)),
                        ha='center', va='bottom')
    
    autolabel(rects1)
    autolabel(rects2)
    
    plt.show()
    

    Esto debería producir el gráfico deseado con el eje y roto en el rango [40, 90].

Comments are closed.