32

Is there a way to change the color of the violin plots in matplotlib?

The default color is this "brownish" color, which is not too bad, but I'd like to color e.g., the first 3 violins differently to highlight them. I don't find any parameter in the documentation. Any ideas or hacks to color the violins differently?

enter image description here

Georgy
  • 12,464
  • 7
  • 65
  • 73
  • Can you open a feature request to add that functionality? Violin plots a a new feature in 1.4 and (apparently) still need some refining. – tacaswell Oct 10 '14 at 13:58

3 Answers3

48

matplotlib.pyplot.violinplot() says it returns:

A dictionary mapping each component of the violinplot to a list of the corresponding collection instances created. The dictionary has the following keys:

  • bodies: A list of the matplotlib.collections.PolyCollection instances containing the filled area of each violin.
  • [...among others...]

Methods of PolyCollections include:

So, it looks like you could just loop through the result's body list and modify the facecolor of each:

violin_parts = plt.violinplot(...)

for pc in violin_parts['bodies']:
    pc.set_facecolor('red')
    pc.set_edgecolor('black')

It is a bit strange though that you can't set this when creating it like the common plot types. I'd guess it's probably because the operation creates so many bits (the aforementioned PolyCollection along with 5 other LineCollections), that additional arguments would be ambiguous.

Community
  • 1
  • 1
Nick T
  • 25,754
  • 12
  • 83
  • 121
  • 2
    Thanks, `for patch, color in zip(vplot['bodies'], colors): patch.set_color(color)` did the job! –  Oct 10 '14 at 03:51
  • 1
    Or using `plt.setp` for short, e.g. `plt.setp(violin_parts['bodies'], facecolor='red', edgecolor='black')` – Syrtis Major Jun 13 '17 at 13:29
  • 2
    Just wanted to say that `violin_parts.keys()` will list all different parts you can adjust. For example: `dict_keys(['bodies', 'cmaxes', 'cmins', 'cbars', 'cmedians'])`. Then, `dir(violin_parts['cbars'])` will list attributes you can set. For example: `violin_parts['cbars'].set_linewidth(1)` – blaylockbk Feb 08 '19 at 16:42
16
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

rrred = '#ff2222'
bluuu = '#2222ff'
x = np.arange(2, 25)
y = np.array([xi * np.random.uniform(0, 1, 10**3) for xi in x]).T

# Create violin plot objects:
fig, ax = plt.subplots(1, 1, figsize = (8,8))
violin_parts = ax.violinplot(y, x, widths = 0.9, showmeans = True, showextrema = True, showmedians = True)

# Make all the violin statistics marks red:
for partname in ('cbars','cmins','cmaxes','cmeans','cmedians'):
    vp = violin_parts[partname]
    vp.set_edgecolor(rrred)
    vp.set_linewidth(1)

# Make the violin body blue with a red border:
for vp in violin_parts['bodies']:
    vp.set_facecolor(bluuu)
    vp.set_edgecolor(rrred)
    vp.set_linewidth(1)
    vp.set_alpha(0.5)

enter image description here

Joel Bondurant
  • 841
  • 1
  • 10
  • 17
  • 1
    Since you don't know whether means etc. are enabled, you could simply loop through all available parts with `for partname in violin_parts`. However, as the `'bodies'` part is a list itself, you'd have to skip that one (with `if partname == 'bodies': continue`) and handle it manually. (Based on what I learned from the comments on @Nick T's answer.) – F1iX Dec 09 '22 at 17:41
1

Suppose you have 3 vectors: data1, data2, data3; and you have plotted your matplotlib violinplots in one figure; then, to set the color of the median line and body facecolor specific for each sub-violinplot you can use:

colors = ['Blue', 'Green', 'Purple']

# Set the color of the violin patches
for pc, color in zip(plots['bodies'], colors):
    pc.set_facecolor(color)

# Set the color of the median lines
plots['cmedians'].set_colors(colors)

The full example:

# Set up the figure and axis
fig, ax = plt.subplots(1, 1)

# Create a list of the data to be plotted
data = [data1, data2, data3]

# Set the colors for the violins based on the category
colors = ['Blue', 'Green', 'Purple']

# Create the violin plot
plots = ax.violinplot(data, vert=False, showmedians=True, showextrema=False, widths=1)

# Set the color of the violin patches
for pc, color in zip(plots['bodies'], colors):
    pc.set_facecolor(color)

# Set the color of the median lines
plots['cmedians'].set_colors(colors)

# Set the labels
ax1.set_yticks([1, 2, 3], labels=['category1', 'category2', 'category3'])

ax1.invert_yaxis() # ranking from top to bottom: invert yaxis

plt.show()

Example for matplotlib violin plots with different colors

  • Thanks! This is actually the only complete answer (showing how to change colors of all elements, not only the violin body.) Adding a figure could greatly improve its visibility. – Roger Vadim Jun 01 '23 at 14:42