22

I try to add the legend which should, according to my example, output:

  1. a red square with the word fruit and
  2. a green square with the word veggie.

I tried several things (the example below is just 1 of the many trials), but I can't get it work.

Can someone tell me how to solve this problem?

import pandas as pd
from matplotlib import pyplot as plt
data = [['apple', 'fruit', 10], ['nanaba', 'fruit', 15], ['salat','veggie', 144]] 
data = pd.DataFrame(data, columns = ['Object', 'Type', 'Value']) 

colors = {'fruit':'red', 'veggie':'green'}           
c = data['Type'].apply(lambda x: colors[x])

bars = plt.bar(data['Object'], data['Value'], color=c, label=colors)
plt.legend()

plot

S12000
  • 3,345
  • 12
  • 35
  • 51

2 Answers2

44

The usual way to create a legend for objects which are not in the axes would be to create proxy artists as shown in the legend guide

Here,

colors = {'fruit':'red', 'veggie':'green'}         
labels = list(colors.keys())
handles = [plt.Rectangle((0,0),1,1, color=colors[label]) for label in labels]
plt.legend(handles, labels)

enter image description here

ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712
2

So this is a hacky solution and I'm sure there are probably better ways to do this. What you can do is plot individual bar plots that are invisible using width=0 with the original plot colors and specify the labels. You will have to do this in a subplot though.

import pandas as pd
from matplotlib import pyplot as plt

data = [['apple', 'fruit', 10], ['nanaba', 'fruit', 15], ['salat','veggie', 144]] 
data = pd.DataFrame(data, columns = ['Object', 'Type', 'Value']) 


colors = {'fruit':'red', 'veggie':'green'}
c = data['Type'].apply(lambda x: colors[x])


ax = plt.subplot(111) #specify a subplot

bars = ax.bar(data['Object'], data['Value'], color=c) #Plot data on subplot axis

for i, j in colors.items(): #Loop over color dictionary
    ax.bar(data['Object'], data['Value'],width=0,color=j,label=i) #Plot invisible bar graph but have the legends specified

ax.legend()

plt.show()

enter image description here

BenT
  • 3,172
  • 3
  • 18
  • 38
  • 1
    Hi, thanks. It works, I will use your solution now. However, I will just let the post open in case someone else suggest another solution as you said it's a 'hacky solution'. – S12000 Aug 03 '19 at 18:50