1
1
"""
2
- =============
3
- Barchart Demo
4
- =============
5
-
6
- Bar charts of many shapes and sizes with Matplotlib.
2
+ ===================================
3
+ Percentiles as horizontal bar chart
4
+ ===================================
7
5
8
6
Bar charts are useful for visualizing counts, or summary statistics
9
- with error bars. These examples show a few ways to do this with Matplotlib.
7
+ with error bars. Also see the :doc:`/gallery/lines_bars_and_markers/barchart`
8
+ or the :doc:`/gallery/lines_bars_and_markers/barh` example for simpler versions
9
+ of those features.
10
+
11
+ This example comes from an application in which grade school gym
12
+ teachers wanted to be able to show parents how their child did across
13
+ a handful of fitness tests, and importantly, relative to how other
14
+ children did. To extract the plotting code for demo purposes, we'll
15
+ just make up some data for little Johnny Doe.
10
16
"""
11
17
12
- ###############################################################################
13
- # A bar plot with errorbars and height labels on individual bars.
14
-
15
- # Credit: Josh Hemann
16
-
17
18
import numpy as np
19
+ import matplotlib
18
20
import matplotlib .pyplot as plt
19
21
from matplotlib .ticker import MaxNLocator
20
22
from collections import namedtuple
21
23
22
-
23
- men_means , men_std = (20 , 35 , 30 , 35 , 27 ), (2 , 3 , 4 , 1 , 2 )
24
- women_means , women_std = (25 , 32 , 34 , 20 , 25 ), (3 , 5 , 2 , 3 , 3 )
25
-
26
- ind = np .arange (len (men_means )) # the x locations for the groups
27
- width = 0.35 # the width of the bars
28
-
29
- fig , ax = plt .subplots ()
30
- rects1 = ax .bar (ind - width / 2 , men_means , width , yerr = men_std ,
31
- label = 'Men' )
32
- rects2 = ax .bar (ind + width / 2 , women_means , width , yerr = women_std ,
33
- label = 'Women' )
34
-
35
- # Add some text for labels, title and custom x-axis tick labels, etc.
36
- ax .set_ylabel ('Scores' )
37
- ax .set_title ('Scores by group and gender' )
38
- ax .set_xticks (ind )
39
- ax .set_xticklabels (('G1' , 'G2' , 'G3' , 'G4' , 'G5' ))
40
- ax .legend ()
41
-
42
-
43
- def autolabel (rects , xpos = 'center' ):
44
- """
45
- Attach a text label above each bar in *rects*, displaying its height.
46
-
47
- *xpos* indicates which side to place the text w.r.t. the center of
48
- the bar. It can be one of the following {'center', 'right', 'left'}.
49
- """
50
-
51
- ha = {'center' : 'center' , 'right' : 'left' , 'left' : 'right' }
52
- offset = {'center' : 0.5 , 'right' : 0.57 , 'left' : 0.43 } # x_txt = x + w*off
53
-
54
- for rect in rects :
55
- height = rect .get_height ()
56
- ax .text (rect .get_x () + rect .get_width () * offset [xpos ], 1.01 * height ,
57
- '{}' .format (height ), ha = ha [xpos ], va = 'bottom' )
58
-
59
-
60
- autolabel (rects1 , "left" )
61
- autolabel (rects2 , "right" )
62
-
63
- fig .tight_layout ()
64
-
65
-
66
- ###############################################################################
67
- # This example comes from an application in which grade school gym
68
- # teachers wanted to be able to show parents how their child did across
69
- # a handful of fitness tests, and importantly, relative to how other
70
- # children did. To extract the plotting code for demo purposes, we'll
71
- # just make up some data for little Johnny Doe...
24
+ np .random .seed (42 )
72
25
73
26
Student = namedtuple ('Student' , ['name' , 'grade' , 'gender' ])
74
27
Score = namedtuple ('Score' , ['score' , 'percentile' ])
@@ -142,10 +95,6 @@ def plot_student_results(student, scores, cohort_size):
142
95
143
96
# Plot a solid vertical gridline to highlight the median position
144
97
ax1 .axvline (50 , color = 'grey' , alpha = 0.25 )
145
- # set X-axis tick marks at the deciles
146
- cohort_label = ax1 .text (.5 , - .07 , 'Cohort Size: {0}' .format (cohort_size ),
147
- horizontalalignment = 'center' , size = 'small' ,
148
- transform = ax1 .transAxes )
149
98
150
99
# Set the right-hand Y-axis ticks and labels
151
100
ax2 = ax1 .twinx ()
@@ -163,10 +112,11 @@ def plot_student_results(student, scores, cohort_size):
163
112
164
113
ax2 .set_ylabel ('Test Scores' )
165
114
166
- ax2 .set_xlabel (('Percentile Ranking Across '
167
- '{grade} Grade {gender}s' ).format (
168
- grade = attach_ordinal (student .grade ),
169
- gender = student .gender .title ()))
115
+ xlabel = ('Percentile Ranking Across {grade} Grade {gender}s\n '
116
+ 'Cohort Size: {cohort_size}' )
117
+ ax1 .set_xlabel (xlabel .format (grade = attach_ordinal (student .grade ),
118
+ gender = student .gender .title (),
119
+ cohort_size = cohort_size ))
170
120
171
121
rect_labels = []
172
122
# Lastly, write in the ranking inside each bar to aid in interpretation
@@ -178,24 +128,25 @@ def plot_student_results(student, scores, cohort_size):
178
128
179
129
rankStr = attach_ordinal (width )
180
130
# The bars aren't wide enough to print the ranking inside
181
- if width < 5 :
131
+ if width < 40 :
182
132
# Shift the text to the right side of the right edge
183
- xloc = width + 1
133
+ xloc = 5
184
134
# Black against white background
185
135
clr = 'black'
186
136
align = 'left'
187
137
else :
188
138
# Shift the text to the left side of the right edge
189
- xloc = 0.98 * width
139
+ xloc = - 5
190
140
# White on magenta
191
141
clr = 'white'
192
142
align = 'right'
193
143
194
144
# Center the text vertically in the bar
195
145
yloc = rect .get_y () + rect .get_height () / 2
196
- label = ax1 .text (xloc , yloc , rankStr , horizontalalignment = align ,
197
- verticalalignment = 'center' , color = clr , weight = 'bold' ,
198
- clip_on = True )
146
+ label = ax1 .annotate (rankStr , xy = (width , yloc ), xytext = (xloc , 0 ),
147
+ textcoords = "offset points" ,
148
+ ha = align , va = 'center' ,
149
+ color = clr , weight = 'bold' , clip_on = True )
199
150
rect_labels .append (label )
200
151
201
152
# make the interactive mouse over give the bar title
@@ -205,8 +156,7 @@ def plot_student_results(student, scores, cohort_size):
205
156
'ax' : ax1 ,
206
157
'ax_right' : ax2 ,
207
158
'bars' : rects ,
208
- 'perc_labels' : rect_labels ,
209
- 'cohort_label' : cohort_label }
159
+ 'perc_labels' : rect_labels }
210
160
211
161
212
162
student = Student ('Johnny Doe' , 2 , 'boy' )
@@ -219,3 +169,20 @@ def plot_student_results(student, scores, cohort_size):
219
169
220
170
arts = plot_student_results (student , scores , cohort_size )
221
171
plt .show ()
172
+
173
+
174
+ #############################################################################
175
+ #
176
+ # ------------
177
+ #
178
+ # References
179
+ # """"""""""
180
+ #
181
+ # The use of the following functions, methods and classes is shown
182
+ # in this example:
183
+
184
+ matplotlib .axes .Axes .bar
185
+ matplotlib .pyplot .bar
186
+ matplotlib .axes .Axes .annotate
187
+ matplotlib .pyplot .annotate
188
+ matplotlib .axes .Axes .twinx
0 commit comments