Attribute Error When Setting Ax Titles On Figure With 2 Axes

Everything works as expected except ax.set_title(). I’m trying to make two pie charts side by side (1,2) and have one main title on top (fig.suptitle()) and two smaller titles for each ax (ax.set_title()).

This is my code:

# Plot
fig, (ax1, ax2) = plt.subplots(1,2)


ax1 = plt.subplot(1,2,1)
ax1 = plt.pie(list_all,
        explode=(0,0.03), 
        startangle=90,
        autopct='%1.1f%%',
        textprops={'fontsize': 10})
ax1.set_title('All Tracks')

ax2 = plt.subplot(1,2,2)
ax2 = plt.pie(list_sold,
        explode=(0,0.03), 
        startangle=90,
        autopct='%1.1f%%',
        textprops={'fontsize': 10})
ax2.set_title('Sold Tracks')


fig.suptitle("Protected v. Not Protected", fontsize=16)
plt.tight_layout()
fig.legend(protected_sold.index, loc='upper left', prop={'size': 10})

When I run it without ax.set_title(), it works fine. When I run it with, it returns this error:

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-75-43817a266915> in <module>
      9         autopct='%1.1f%%',
     10         textprops={'fontsize': 10})
---> 11 ax1.set_title('All Tracks')
     12 
     13 ax2 = plt.subplot(1,2,2)

AttributeError: 'tuple' object has no attribute 'set_title'

Where am I going wrong?

Thank you!

.pie returns a tuple object that contains (patches, texts, autotexts).

# .pie returns a tuple = (patches, texts, autotexts)
# The returned tuple is unable unpacked all onto ax1.
# Not enough variables/labels to unpacked tuple, needs 3 labels.
ax1 = plt.pie(list_all,
        explode=(0,0.03), 
        startangle=90,
        autopct='%1.1f%%',
        textprops={'fontsize': 10})
ax1.set_title('All Tracks')

Should work below (didn’t test)

patches, texts, autotexts = ax1.pie(list_all,
        explode=(0,0.03), 
        startangle=90,
        autopct='%1.1f%%',
        textprops={'fontsize': 10})
ax1.set_title("All Tracks")

or

ax1.set(aspect="equal", title='All Tracks')
1 Like

That works! Thank you!

Also in this project I had this single plt.pie with was fine:

# Plot
plt.pie(list5, 
        labels=album.index,
        explode=(0,0.03), 
        startangle=90,
        autopct='%1.1f%%',
        textprops={'fontsize': 3})

plt.tight_layout()
plt.title('Album v. Individual Tracks', fontsize=4)
fig = plt.gcf()
fig.set_size_inches(1,1)

Why did plt.set_title() work in that case?

In general, how does what plt.pie returns determine how you will set up your plot and plot aesthetics?

In this project, I’ve also used sns.barplot. I see from that documentation that it returns ax: Matplotlib axes. The ax.set_title() worked fine in that case. Is that because it returned an ax: Matplotlib axes object?

I’ve been trying to get a deeper understanding of the mechanics of plotting and fine tuning the aesthetics.

Thank you for your time!

plt.set_title() will work because plt is the main plot.

The issues is because of your assignment of ax1 = plt.pie. Now, ax1 is not Matplotlib axes object anymore, but a tuple.

1 Like