Created
September 17, 2012 11:01
-
-
Save dmcdougall/3736702 to your computer and use it in GitHub Desktop.
Axes boxplot method
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def boxplot(self, x, notch=0, sym='b+', vert=1, whis=1.5, | |
positions=None, widths=None, means=0, dofill=1, | |
linestyle='-', monochrome=0, limits=None): | |
""" | |
boxplot(x, notch=0, sym='+', vert=1, whis=1.5, | |
positions=None, widths=None, means=0, dofill=1, | |
linestyle='-', monochrome=0, limits=None) | |
Make a box and whisker plot for each column of x. | |
The box extends from the lower to upper quartile values | |
of the data, with a line at the median. The whiskers | |
extend from the box to show the range of the data. Flier | |
points are those past the end of the whiskers. | |
notch = 0 (default) produces a rectangular box plot. | |
notch = 1 will produce a notched box plot | |
sym (default 'b+') is the default symbol for flier points. | |
Enter an empty string ('') if you don't want to show fliers. | |
vert = 1 (default) makes the boxes vertical. | |
vert = 0 makes horizontal boxes. This seems goofy, but | |
that's how Matlab did it. | |
whis (default 1.5) defines the length of the whiskers as | |
a function of the inner quartile range. They extend to the | |
most extreme data point within ( whis*(75%-25%) ) data range. | |
positions (default 1,2,...,n) sets the horizontal positions of | |
the boxes. The ticks and limits are automatically set to match | |
the positions. | |
widths is either a scalar or a vector and sets the width of | |
each box. The default is 0.5, or 0.15*(distance between extreme | |
positions) if that is smaller. | |
means = 0 (default) does not indicate the mean of the data. | |
means = 1 plots a dashed black line in the box indicating | |
the mean of the data. | |
linestyle sets the line style of the whiskers. | |
monochrome = 0 (default) uses color in the plot. | |
monochrome = 1 uses a monochrome color scheme. | |
dofill = 1 (default) fills the box in white | |
dofill = 0 leaves the box alone | |
x is a Numeric array | |
Returns a list of the lines added | |
""" | |
if not self._hold: | |
self.cla() | |
holdStatus = self._hold | |
lines = [] | |
x = asarray(x) | |
# if we've got a vector, reshape it | |
rank = len(x.shape) | |
if 1 == rank: | |
x.shape = -1, 1 | |
row, col = x.shape | |
# get some plot info | |
if positions is None: | |
positions = range(1, col + 1) | |
if widths is None: | |
distance = max(1,max(positions) - min(positions)) | |
widths = distance * min(0.15, 0.5/distance) | |
if isinstance(widths, float) or isinstance(widths, int): | |
widths = ones((col,), 'd') * widths | |
# loop through columns, adding each to plot | |
self.hold(True) | |
for i,pos in enumerate(positions): | |
d = x[:,i] | |
# get mean | |
mean = sum(d)/len(d) | |
# get median and quartiles | |
q1, med, q3 = prctile(d,[25,50,75]) | |
# get high extreme | |
iq = q3 - q1 | |
hi_val = q3 + whis*iq | |
wisk_hi = compress( d <= hi_val , d ) | |
if len(wisk_hi) == 0: | |
wisk_hi = q3 | |
else: | |
wisk_hi = max(wisk_hi) | |
# get low extreme | |
lo_val = q1 - whis*iq | |
wisk_lo = compress( d >= lo_val, d ) | |
if len(wisk_lo) == 0: | |
wisk_lo = q1 | |
else: | |
wisk_lo = min(wisk_lo) | |
# get fliers - if we are showing them | |
flier_hi = [] | |
flier_lo = [] | |
flier_hi_x = [] | |
flier_lo_x = [] | |
if len(sym) != 0: | |
flier_hi = compress( d > wisk_hi, d ) | |
flier_lo = compress( d < wisk_lo, d ) | |
flier_hi_x = ones(flier_hi.shape[0]) * pos | |
flier_lo_x = ones(flier_lo.shape[0]) * pos | |
# get x locations for fliers, whisker, whisker cap and box sides | |
box_x_min = pos - widths[i] * 0.5 | |
box_x_max = pos + widths[i] * 0.5 | |
wisk_x = ones(2) * pos | |
cap_x_min = pos - widths[i] * 0.25 | |
cap_x_max = pos + widths[i] * 0.25 | |
cap_x = [cap_x_min, cap_x_max] | |
# get y location for median, mean | |
med_y = [med, med] | |
mean_y = [mean, mean] | |
# calculate 'regular' plot | |
if notch == 0: | |
# make our box vectors | |
box_x = [box_x_min, box_x_max, box_x_max, box_x_min, box_x_min] | |
box_y = [q1, q1, q3, q3, q1 ] | |
# make our median, mean line vectors | |
med_x = [box_x_min, box_x_max] | |
mean_x = [box_x_min, box_x_max] | |
# calculate 'notch' plot | |
else: | |
notch_max = med + 1.57*iq/sqrt(row) | |
notch_min = med - 1.57*iq/sqrt(row) | |
if notch_max > q3: | |
notch_max = q3 | |
if notch_min < q1: | |
notch_min = q1 | |
# make our notched box vectors | |
box_x = [box_x_min, box_x_max, box_x_max, cap_x_max, box_x_max, box_x_max, box_x_min, box_x_min, cap_x_min, box_x_min, box_x_min] | |
box_y = [q1, q1, notch_min, med, notch_max, q3, q3, notch_max, med, notch_min, q1] | |
# make our median, mean line vectors | |
med_x = [cap_x_min, cap_x_max] | |
mean_x = [box_x_min, box_x_max] # doesn't take into account notch cap | |
if monochrome: | |
wiskcol = capcol = boxcol = medcol = 'k' | |
else: | |
wiskcol, capcol, boxcol, medcol = 'b', 'k', 'b', 'r' | |
# make a vertical plot . . . | |
if dofill: | |
self.fill(box_x, box_y, facecolor='w') | |
if 1 == vert: | |
l = self.plot(wisk_x, [q1, wisk_lo], wiskcol+linestyle, | |
wisk_x, [q3, wisk_hi], wiskcol+linestyle, | |
cap_x, [wisk_hi, wisk_hi], capcol+'-', | |
cap_x, [wisk_lo, wisk_lo], capcol+'-', | |
box_x, box_y, boxcol+'-', | |
med_x, med_y, medcol+'-', | |
flier_hi_x, flier_hi, sym, | |
flier_lo_x, flier_lo, sym ) | |
if means: | |
l.append(self.plot(mean_x, mean_y, 'k:')) | |
lines.extend(l) | |
# or perhaps a horizontal plot | |
else: | |
l = self.plot([q1, wisk_lo], wisk_x, wiskcol+linestyle, | |
[q3, wisk_hi], wisk_x, wiskcol+linestyle, | |
[wisk_hi, wisk_hi], cap_x, capcol+'-', | |
[wisk_lo, wisk_lo], cap_x, capcol+'-', | |
box_y, box_x, boxcol+'-', | |
med_y, med_x, medcol+'-', | |
flier_hi, flier_hi_x, sym, | |
flier_lo, flier_lo_x, sym ) | |
if means: | |
l.append(self.plot(mean_x, mean_y, 'k:')) | |
lines.extend(l) | |
# fix our axes/ticks up a little | |
if 1 == vert: | |
setticks, setlim = self.set_xticks, self.set_xlim | |
else: | |
setticks, setlim = self.set_yticks, self.set_ylim | |
if limits is None: | |
newlimits = min(positions)-0.5, max(positions)+0.5 | |
setlim(newlimits) | |
setticks(positions) | |
elif limits != (): | |
setlim(limits) | |
setticks([]) | |
# reset hold status | |
self.hold(holdStatus) | |
return lines |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment