55import matplotlib .pyplot as plt
66import numpy as np
77
8+
89# functions to calculate percentiles and adjacent values
9- def percentile (vals ,p ):
10+ def percentile (vals , p ):
1011 N = len (vals )
1112 n = p * (N + 1 )
1213 k = int (n )
1314 d = n - k
14- if k <= 0 : return vals [0 ]
15- if k >= N : return vals [N - 1 ]
15+ if k <= 0 :
16+ return vals [0 ]
17+ if k >= N :
18+ return vals [N - 1 ]
1619 return vals [k - 1 ] + d * (vals [k ] - vals [k - 1 ])
1720
21+
1822def adjacent_values (vals ):
19- q1 = percentile (vals ,0.25 )
20- q3 = percentile (vals ,0.75 )
23+ q1 = percentile (vals , 0.25 )
24+ q3 = percentile (vals , 0.75 )
2125 uav = q3 + (q3 - q1 )* 1.5
22- if uav > vals [- 1 ]: uav = vals [- 1 ]
23- if uav < q3 : uav = q3
26+ if uav > vals [- 1 ]:
27+ uav = vals [- 1 ]
28+ if uav < q3 :
29+ uav = q3
2430 lav = q1 - (q3 - q1 )* 1.5
25- if lav < vals [0 ]: lav = vals [0 ]
26- if lav > q1 : lav = q1
27- return [lav ,uav ]
31+ if lav < vals [0 ]:
32+ lav = vals [0 ]
33+ if lav > q1 :
34+ lav = q1
35+ return [lav , uav ]
2836
2937# create test data
3038dat = [np .random .normal (0 , std , 100 ) for std in range (6 , 10 )]
31- lab = ['a' ,'b' ,'c' ,'d' ] # labels
39+ lab = ['a' , 'b' , 'c' , 'd' ] # labels
3240med = [] # medians
3341iqr = [] # inter-quantile ranges
3442avs = [] # upper and lower adjacent values
3543for arr in dat :
3644 sarr = sorted (arr )
37- med .append (percentile (sarr ,0.5 ))
38- iqr .append ([percentile (sarr ,0.25 ),percentile (sarr ,0.75 )])
45+ med .append (percentile (sarr , 0.5 ))
46+ iqr .append ([percentile (sarr , 0.25 ), percentile (sarr , 0.75 )])
3947 avs .append (adjacent_values (sarr ))
4048
4149# plot the violins
42- fig , ax = plt .subplots (nrows = 1 , ncols = 1 , figsize = (7 ,5 ))
43- parts = ax .violinplot (dat ,showmeans = False ,showmedians = False ,showextrema = False )
50+ fig , ax = plt .subplots (nrows = 1 , ncols = 1 , figsize = (7 , 5 ))
51+ parts = ax .violinplot (dat , showmeans = False , showmedians = False ,
52+ showextrema = False )
4453
4554# plot medians and averages
4655for i in range (len (med )):
47- ax .plot ([i + 1 ,i + 1 ],avs [i ],'-' ,c = 'black' ,lw = 1 )
48- ax .plot ([i + 1 ,i + 1 ],iqr [i ],'-' ,c = 'black' ,lw = 5 )
49- ax .plot (i + 1 ,med [i ],'o' ,mec = 'none' ,c = 'white' ,ms = 6 )
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 )
5059
5160# customize colors
5261for pc in parts ['bodies' ]:
@@ -58,13 +67,11 @@ def adjacent_values(vals):
5867ax .xaxis .set_ticks_position ('bottom' )
5968ax .set_xticks ([x + 1 for x in range (len (lab ))])
6069ax .set_xticklabels (lab )
61- ax .set_xlim (0.25 ,len (lab )+ 0.75 )
70+ ax .set_xlim (0.25 , len (lab )+ 0.75 )
6271ax .set_ylabel ('ylabel' )
6372ax .set_xlabel ('xlabel' )
6473ax .set_title ('customized violin plot' )
6574
6675plt .subplots_adjust (bottom = 0.15 )
6776
6877plt .show ()
69-
70-
0 commit comments