matplotlib - making labels for violin plots
Here is my solution for multple violin plots. Note that it grabs the patch color from the first shaded area of the given violin plot---this could be changed to do something else if there are multiple colors, or you could instead grab the color of the vertical bar with violin["cbars"].get_color().flatten()
.
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
import numpy as np
labels = []
def add_label(violin, label):
color = violin["bodies"][0].get_facecolor().flatten()
labels.append((mpatches.Patch(color=color), label))
positions = np.arange(3,13,3)
data = np.random.randn(1000, len(positions))
add_label(plt.violinplot(data, positions), "Flat")
positions = np.arange(1, 10, 2)
data = np.random.randn(1000, len(positions)) + positions
add_label(plt.violinplot(data, positions), "Linear")
positions = np.arange(2, 11, 1)
data = np.random.randn(1000, len(positions)) + positions ** 2 / 4
add_label(plt.violinplot(data, positions), "Quadratic")
plt.legend(*zip(*labels), loc=2)
As it was mentioned in comment, some plots in matplotlib don't support legends. Documentation still provides a simple way to add custom legends for them: http://matplotlib.org/users/legend_guide.html#proxy-legend-handles
Main idea : add 'fake' objects, which can be not shown in the plot, then use it to form a handles list for legend method.
import random
import numpy as np
import matplotlib.pyplot as pl
import matplotlib.patches as mpatches
from itertools import repeat
red_patch = mpatches.Patch(color='red')
# 'fake' invisible object
pos = [1, 2, 4, 5, 7, 8]
label = ['plot 1','plot2','ghi','jkl','mno','pqr']
data = [np.random.normal(size=100) for i in pos]
fake_handles = repeat(red_patch, len(pos))
pl.figure()
ax = pl.subplot(111)
pl.violinplot(data, pos, vert=False)
ax.legend(fake_handles, label)
pl.show()
There is an even simpler solution than @Ian Hincks code, without using mpatches
import matplotlib.pyplot as plt
import numpy as np
positions = np.arange(3,13,3)
data = np.random.randn(1000, len(positions))
vp1 = plt.violinplot(data, positions)
positions = np.arange(1, 10, 2)
data = np.random.randn(1000, len(positions)) + positions
vp2 = plt.violinplot(data, positions)
positions = np.arange(2, 11, 1)
data = np.random.randn(1000, len(positions)) + positions ** 2 / 4
vp3 = plt.violinplot(data, positions)
plt.legend([vp1['bodies'][0],vp2['bodies'][0], vp3['bodies'][0]], ['flat', 'linear', 'quadratic'], loc=2)[enter image description here][1]
To use the lines instead of the bodies replace vp1['bodies'][0]
by vp1['cbars']
demo: violin plot with labels