1- # Customizing violin plots
2- #
3- #
1+ """
2+ =================================
3+ Demo of violin plot customization
4+ =================================
5+
6+ This example demonstrates how to fully customize violin plots.
7+ The first plot shows the default style by providing only
8+ the data. The second plot first limits what matplotlib draws
9+ with additional kwargs. Then a simplified representation of
10+ a box plot is drawn on top. Lastly, the styles of the artists
11+ of the violins are modified.
12+
13+ For more information on violin plots, the scikit-learn docs have a great
14+ section: http://scikit-learn.org/stable/modules/density.html
15+ """
416
517import matplotlib .pyplot as plt
618import numpy as np
@@ -22,21 +34,28 @@ def percentile(vals, p):
2234def adjacent_values (vals ):
2335 q1 = percentile (vals , 0.25 )
2436 q3 = percentile (vals , 0.75 )
25- uav = q3 + (q3 - q1 )* 1.5
37+ iqr = q3 - q1 # inter-quartile range
38+
39+ # upper adjacent values
40+ uav = q3 + iqr * 1.5
2641 if uav > vals [- 1 ]:
2742 uav = vals [- 1 ]
2843 if uav < q3 :
2944 uav = q3
30- lav = q1 - (q3 - q1 )* 1.5
45+
46+ # lower adjacent values
47+ lav = q1 - iqr * 1.5
3148 if lav < vals [0 ]:
3249 lav = vals [0 ]
3350 if lav > q1 :
3451 lav = q1
3552 return [lav , uav ]
3653
54+
3755# create test data
38- dat = [np .random .normal (0 , std , 100 ) for std in range (6 , 10 )]
39- lab = ['a' , 'b' , 'c' , 'd' ] # labels
56+ np .random .seed (123 )
57+ dat = [np .random .normal (0 , std , 100 ) for std in range (1 , 5 )]
58+ lab = ['A' , 'B' , 'C' , 'D' ] # labels
4059med = [] # medians
4160iqr = [] # inter-quantile ranges
4261avs = [] # upper and lower adjacent values
@@ -47,31 +66,39 @@ def adjacent_values(vals):
4766 avs .append (adjacent_values (sarr ))
4867
4968# plot the violins
50- fig , ax = plt .subplots (nrows = 1 , ncols = 1 , figsize = (7 , 5 ))
51- parts = ax .violinplot (dat , showmeans = False , showmedians = False ,
52- showextrema = False )
69+ fig , (ax1 , ax2 ) = plt .subplots (nrows = 1 , ncols = 2 , figsize = (9 , 4 ),
70+ sharey = True )
71+ _ = ax1 .violinplot (dat )
72+ parts = ax2 .violinplot (dat , showmeans = False , showmedians = False ,
73+ showextrema = False )
74+
75+ ax1 .set_title ('Default violin plot' )
76+ ax2 .set_title ('Customized violin plot' )
5377
54- # plot medians and averages
78+ # plot whiskers as thin lines, quartiles as fat lines,
79+ # and medians as points
5580for i in range (len (med )):
56- ax .plot ([i + 1 , i + 1 ], avs [i ], '-' , c = 'black' , lw = 1 )
57- ax .plot ([i + 1 , i + 1 ], iqr [i ], '-' , c = 'black' , lw = 5 )
58- ax .plot (i + 1 , med [i ], 'o' , mec = 'none' , c = 'white' , ms = 6 )
81+ # whiskers
82+ ax2 .plot ([i + 1 , i + 1 ], avs [i ], '-' , color = 'black' , linewidth = 1 )
83+ ax2 .plot ([i + 1 , i + 1 ], iqr [i ], '-' , color = 'black' , linewidth = 5 )
84+ ax2 .plot (i + 1 , med [i ], 'o' , color = 'white' ,
85+ markersize = 6 , markeredgecolor = 'none' )
5986
6087# customize colors
6188for pc in parts ['bodies' ]:
6289 pc .set_facecolor ('#D43F3A' )
6390 pc .set_edgecolor ('black' )
6491 pc .set_alpha (1 )
6592
66- ax . get_xaxis (). set_tick_params ( direction = 'out ' )
67- ax . xaxis . set_ticks_position ( 'bottom' )
68- ax . set_xticks ([ x + 1 for x in range ( len ( lab ))] )
69- ax .set_xticklabels ( lab )
70- ax .set_xlim ( 0.25 , len (lab )+ 0.75 )
71- ax .set_ylabel ( 'ylabel' )
72- ax .set_xlabel ( 'xlabel' )
73- ax .set_title ( 'customized violin plot ' )
93+ ax1 . set_ylabel ( 'Observed values ' )
94+ for ax in [ ax1 , ax2 ]:
95+ ax . get_xaxis (). set_tick_params ( direction = 'out' )
96+ ax .xaxis . set_ticks_position ( 'bottom' )
97+ ax .set_xticks ( np . arange ( 1 , len (lab ) + 1 ) )
98+ ax .set_xticklabels ( lab )
99+ ax .set_xlim ( 0.25 , len ( lab ) + 0.75 )
100+ ax .set_xlabel ( 'Sample name ' )
74101
75- plt .subplots_adjust (bottom = 0.15 )
102+ plt .subplots_adjust (bottom = 0.15 , wspace = 0.05 )
76103
77104plt .show ()
0 commit comments