8000 Merge pull request #7331 from phobson/MEP12-statistic-plots · matplotlib/matplotlib@58cc83d · GitHub
[go: up one dir, main page]

Skip to content

Commit 58cc83d

Browse files
NelleVQuLogic
authored andcommitted
Merge pull request #7331 from phobson/MEP12-statistic-plots
MEP12 improvments for statistics plots
1 parent f8b4f23 commit 58cc83d

15 files changed

+393
-134
lines changed

examples/statistics/boxplot_color_demo.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,17 @@
1-
# Box plots with custom fill colors
1+
"""
2+
=================================
3+
Box plots with custom fill colors
4+
=================================
5+
6+
This plot illustrates how to create two types of box plots
7+
(rectangular and notched), and how to fill them with custom
8+
colors by accessing the properties of the artists of the
9+
box plots. Additionally, the ``labels`` parameter is used to
10+
provide x-tick labels for each sample.
11+
12+
A good general reference on boxplots and their history can be found
13+
here: http://vita.had.co.nz/papers/boxplots.pdf
14+
"""
215

316
import matplotlib.pyplot as plt
417
import numpy as np
@@ -7,7 +20,7 @@
720
np.random.seed(123)
821
all_data = [np.random.normal(0, std, 100) for std in range(1, 4)]
922

10-
fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(12, 5))
23+
fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(9, 4))
1124

1225
# rectangular box plot
1326
bplot1 = axes[0].boxplot(all_data,

examples/statistics/boxplot_demo.py

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,19 @@
11
"""
2-
Demo of the new boxplot functionality
2+
=========================================
3+
Demo of artist customization in box plots
4+
=========================================
5+
6+
This example demonstrates how to use the various kwargs
7+
to fully customize box plots. The first figure demonstrates
8+
how to remove and add individual components (note that the
9+
mean is the only value not shown by default). The second
10+
figure demonstrates how the styles of the artists can
11+
be customized. It also demonstrates how to set the limit
12+
of the whiskers to specific percentiles (lower right axes)
13+
14+
A good general reference on boxplots and their history can be found
15+
here: http://vita.had.co.nz/papers/boxplots.pdf
16+
317
"""
418

519
import numpy as np
@@ -23,7 +37,8 @@
2337
axes[0, 2].set_title('showmeans=True,\nmeanline=True', fontsize=fs)
2438

2539
axes[1, 0].boxplot(data, labels=labels, showbox=False, showcaps=False)
26-
axes[1, 0].set_title('Tufte Style \n(showbox=False,\nshowcaps=False)', fontsize=fs)
40+
tufte_title = 'Tufte Style \n(showbox=False,\nshowcaps=False)'
41+
axes[1, 0].set_title(tufte_title, fontsize=fs)
2742

2843
axes[1, 1].boxplot(data, labels=labels, notch=True, bootstrap=10000)
2944
axes[1, 1].set_title('notch=True,\nbootstrap=10000', fontsize=fs)
@@ -62,7 +77,8 @@
6277
showmeans=True)
6378
axes[1, 0].set_title('Custom mean\nas point', fontsize=fs)
6479

65-
axes[1, 1].boxplot(data, meanprops=meanlineprops, meanline=True, showmeans=True)
80+
axes[1, 1].boxplot(data, meanprops=meanlineprops, meanline=True,
81+
showmean F438 s=True)
6682
axes[1, 1].set_title('Custom mean\nas line', fontsize=fs)
6783

6884
axes[1, 2].boxplot(data, whis=[15, 85])

examples/statistics/boxplot_vs_violin_demo.py

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,29 @@
1-
# Box plot - violin plot comparison
2-
#
3-
# Note that although violin plots are closely related to Tukey's (1977) box plots,
4-
# they add useful information such as the distribution of the sample data (density trace).
5-
#
6-
# By default, box plots show data points outside 1.5 x the inter-quartile range as outliers
7-
# above or below the whiskers wheras violin plots show the whole range of the data.
8-
#
9-
# Violin plots require matplotlib >= 1.4.
1+
"""
2+
===================================
3+
Box plot vs. violin plot comparison
4+
===================================
5+
6+
Note that although violin plots are closely related to Tukey's (1977)
7+
box plots, they add useful information such as the distribution of the
8+
sample data (density trace).
9+
10+
By default, box plots show data points outside 1.5 * the inter-quartile
11+
range as outliers above or below the whiskers whereas violin plots show
12+
the whole range of the data.
13+
14+
A good general reference on boxplots and their history can be found
15+
here: http://vita.had.co.nz/papers/boxplots.pdf
16+
17+
Violin plots require matplotlib >= 1.4.
18+
19+
For more information on violin plots, the scikit-learn docs have a great
20+
section: http://scikit-learn.org/stable/modules/density.html
21+
"""
1022

1123
import matplotlib.pyplot as plt
1224
import numpy as np
1325

14-
fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(12, 5))
26+
fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(9, 4))
1527

1628
# generate some random test data
1729
all_data = [np.random.normal(0, std, 100) for std in range(6, 10)]

examples/statistics/bxp_demo.py

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,17 @@
11
"""
2-
Demo of the new boxplot drawer function
2+
===================================
3+
Demo of the boxplot drawer function
4+
===================================
5+
6+
This example demonstrates how to pass pre-computed box plot
7+
statistics to the box plot drawer. The first figure demonstrates
8+
how to remove and add individual components (note that the
9+
mean is the only value not shown by default). The second
10+
figure demonstrates how the styles of the artists can
11+
be customized.
12+
13+
A good general reference on boxplots and their history can be found
14+
here: http://vita.had.co.nz/papers/boxplots.pdf
315
"""
416

517
import numpy as np
@@ -21,6 +33,7 @@
2133
stats[n]['mean'] *= 2
2234

2335
print(stats[0].keys())
36+
2437
fs = 10 # fontsize
2538

2639
# demonstrate how to toggle the display of different elements:
@@ -35,7 +48,8 @@
3548
axes[0, 2].set_title('showmeans=True,\nmeanline=True', fontsize=fs)
3649

3750
axes[1, 0].bxp(stats, showbox=False, showcaps=False)
38-
axes[1, 0].set_title('Tufte Style\n(showbox=False,\nshowcaps=False)', fontsize=fs)
51+
tufte_title = 'Tufte Style\n(showbox=False,\nshowcaps=False)'
52+
axes[1, 0].set_title(tufte_title, fontsize=fs)
3953

4054
axes[1, 1].bxp(stats, shownotches=True)
4155
axes[1, 1].set_title('notch=True', fontsize=fs)
@@ -50,7 +64,6 @@
5064
fig.subplots_adjust(hspace=0.4)
5165
plt.show()
5266

53-
5467
# demonstrate how to customize the display different elements:
5568
boxprops = dict(linestyle='--', linewidth=3, color='darkgoldenrod')
5669
flierprops = dict(marker='o', markerfacecolor='green', markersize=12,
@@ -71,7 +84,8 @@
7184
showmeans=True)
7285
axes[1, 0].set_title('Custom mean\nas point', fontsize=fs)
7386

74-
axes[1, 1].bxp(stats, meanprops=meanlineprops, meanline=True, showmeans=True)
87+
axes[1, 1].bxp(stats, meanprops=meanlineprops, meanline=True,
88+
showmeans=True)
7589
axes[1, 1].set_title('Custom mean\nas line', fontsize=fs)
7690

7791
for ax in axes.flatten():
Lines changed: 50 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,18 @@
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

517
import matplotlib.pyplot as plt
618
import numpy as np
@@ -22,21 +34,28 @@ def percentile(vals, p):
2234
def 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
4059
med = [] # medians
4160
iqr = [] # inter-quantile ranges
4261
avs = [] # 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
5580
for 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
6188
for 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

77104
plt.show()

examples/statistics/errorbar_demo.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,20 @@
11
"""
2-
Demo of the errorbar function.
2+
=============================
3+
Demo of the errorbar function
4+
=============================
5+
6+
This exhibits the most basic use of the error bar method.
7+
In this case, constant values are provided for the error
8+
in both the x- and y-directions.
39
"""
10+
411
import numpy as np
512
import matplotlib.pyplot as plt
613

714
# example data
815
x = np.arange(0.1, 4, 0.5)
916
y = np.exp(-x)
1017

11-
plt.errorbar(x, y, xerr=0.2, yerr=0.4)
18+
fig, ax = plt.subplots()
19+
ax.errorbar(x, y, xerr=0.2, yerr=0.4)
1220
plt.show()

examples/statistics/errorbar_demo_features.py

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,46 @@
11
"""
2-
Demo of errorbar function with different ways of specifying error bars.
2+
===================================================
3+
Demo of the different ways of specifying error bars
4+
===================================================
35
4-
Errors can be specified as a constant value (as shown in `errorbar_demo.py`),
5-
or as demonstrated in this example, they can be specified by an N x 1 or 2 x N,
6-
where N is the number of data points.
6+
Errors can be specified as a constant value (as shown in
7+
`errorbar_demo.py`). However, this example demonstrates
8+
how they vary by specifying arrays of error values.
79
8-
N x 1:
9-
Error varies for each point, but the error values are symmetric (i.e. the
10-
lower and upper values are equal).
10+
If the raw ``x`` and ``y`` data have length N, there are two options:
1111
12-
2 x N:
13-
Error varies for each point, and the lower and upper limits (in that order)
14-
are different (asymmetric case)
12+
Array of shape (N,):
13+
Error varies for each point, but the error values are
14+
symmetric (i.e. the lower and upper values are equal).
1515
16-
In addition, this example demonstrates how to use log scale with errorbar.
16+
Array of shape (2, N):
17+
Error varies for each point, and the lower and upper limits
18+
(in that order) are different (asymmetric case)
19+
20+
In addition, this example demonstrates how to use log
21+
scale with error bars.
1722
"""
23+
1824
import numpy as np
1925
import matplotlib.pyplot as plt
2026

2127
# example data
2228
x = np.arange(0.1, 4, 0.5)
2329
y = np.exp(-x)
30+
2431
# example error bar values that vary with x-position
2532
error = 0.1 + 0.2 * x
26-
# error bar values w/ different -/+ errors
27-
lower_error = 0.4 * error
28-
upper_error = error
29-
asymmetric_error = [lower_error, upper_error]
3033

3134
fig, (ax0, ax1) = plt.subplots(nrows=2, sharex=True)
3235
ax0.errorbar(x, y, yerr=error, fmt='-o')
3336
ax0.set_title('variable, symmetric error')
3437

38+
# error bar values w/ different -/+ errors that
39+
# also vary with the x-position
40+
lower_error = 0.4 * error
41+
upper_error = error
42+
asymmetric_error = [lower_error, upper_error]
43+
3544
ax1.errorbar(x, y, xerr=asymmetric_error, fmt='o')
3645
ax1.set_title('variable, asymmetric error')
3746
ax1.set_yscale('log')

0 commit comments

Comments
 (0)
0