Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 1c6b59a

Browse filesBrowse files
committed
Merge pull request #7360 from DrNightmare/violinPlotExample
Updated violin plot example as per suggestions in issue #7251
1 parent 1759004 commit 1c6b59a
Copy full SHA for 1c6b59a

File tree

Expand file treeCollapse file tree

1 file changed

+39
-67
lines changed
Filter options
Expand file treeCollapse file tree

1 file changed

+39
-67
lines changed

‎examples/statistics/customized_violin_demo.py

Copy file name to clipboardExpand all lines: examples/statistics/customized_violin_demo.py
+39-67Lines changed: 39 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -18,87 +18,59 @@
1818
import numpy as np
1919

2020

21-
# functions to calculate percentiles and adjacent values
22-
def percentile(vals, p):
23-
N = len(vals)
24-
n = p*(N+1)
25-
k = int(n)
26-
d = n-k
27-
if k <= 0:
28-
return vals[0]
29-
if k >= N:
30-
return vals[N-1]
31-
return vals[k-1] + d*(vals[k] - vals[k-1])
32-
33-
34-
def adjacent_values(vals):
35-
q1 = percentile(vals, 0.25)
36-
q3 = percentile(vals, 0.75)
37-
iqr = q3 - q1 # inter-quartile range
38-
39-
# upper adjacent values
40-
uav = q3 + iqr * 1.5
41-
if uav > vals[-1]:
42-
uav = vals[-1]
43-
if uav < q3:
44-
uav = q3
45-
46-
# lower adjacent values
47-
lav = q1 - iqr * 1.5
48-
if lav < vals[0]:
49-
lav = vals[0]
50-
if lav > q1:
51-
lav = q1
52-
return [lav, uav]
21+
def adjacent_values(vals, q1, q3):
22+
upper_adjacent_value = q3 + (q3 - q1) * 1.5
23+
upper_adjacent_value = np.clip(upper_adjacent_value, q3, vals[-1])
24+
25+
lower_adjacent_value = q1 - (q3 - q1) * 1.5
26+
lower_adjacent_value = np.clip(lower_adjacent_value, vals[0], q1)
27+
return lower_adjacent_value, upper_adjacent_value
28+
29+
30+
def set_axis_style(ax, labels):
31+
ax.get_xaxis().set_tick_params(direction='out')
32+
ax.xaxis.set_ticks_position('bottom')
33+
ax.set_xticks(np.arange(1, len(labels) + 1))
34+
ax.set_xticklabels(labels)
35+
ax.set_xlim(0.25, len(labels) + 0.75)
36+
ax.set_xlabel('Sample name')
5337

5438

5539
# create test data
5640
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
59-
med = [] # medians
60-
iqr = [] # inter-quantile ranges
61-
avs = [] # upper and lower adjacent values
62-
for arr in dat:
63-
sarr = sorted(arr)
64-
med.append(percentile(sarr, 0.5))
65-
iqr.append([percentile(sarr, 0.25), percentile(sarr, 0.75)])
66-
avs.append(adjacent_values(sarr))
67-
68-
# plot the violins
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)
41+
data = [sorted(np.random.normal(0, std, 100)) for std in range(1, 5)]
42+
43+
fig, (ax1, ax2) = plt.subplots(nrows=1, ncols=2, figsize=(9, 4), sharey=True)
7444

7545
ax1.set_title('Default violin plot')
76-
ax2.set_title('Customized violin plot')
46+
ax1.set_ylabel('Observed values')
47+
ax1.violinplot(data)
7748

78-
# plot whiskers as thin lines, quartiles as fat lines,
79-
# and medians as points
80-
for i in range(len(med)):
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')
49+
ax2.set_title('Customized violin plot')
50+
parts = ax2.violinplot(
51+
data, showmeans=False, showmedians=False,
52+
showextrema=False)
8653

87-
# customize colors
8854
for pc in parts['bodies']:
8955
pc.set_facecolor('#D43F3A')
9056
pc.set_edgecolor('black')
9157
pc.set_alpha(1)
9258

93-
ax1.set_ylabel('Observed values')
59+
quartile1, medians, quartile3 = np.percentile(data, [25, 50, 75], axis=1)
60+
whiskers = np.array([
61+
adjacent_values(sorted_array, q1, q3)
62+
for sorted_array, q1, q3 in zip(data, quartile1, quartile3)])
63+
whiskersMin, whiskersMax = whiskers[:, 0], whiskers[:, 1]
64+
65+
inds = np.arange(1, len(medians) + 1)
66+
ax2.scatter(inds, medians, marker='o', color='white', s=30, zorder=3)
67+
ax2.vlines(inds, quartile1, quartile3, color='k', linestyle='-', lw=5)
68+
ax2.vlines(inds, whiskersMin, whiskersMax, color='k', linestyle='-', lw=1)
69+
70+
# set style for the axes
71+
labels = ['A', 'B', 'C', 'D']
9472
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')
73+
set_axis_style(ax, labels)
10174

10275
plt.subplots_adjust(bottom=0.15, wspace=0.05)
103-
10476
plt.show()

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.