Skip to content

Commit 122eb6a

Browse files
committed
added boxplot patch
svn path=/trunk/matplotlib/; revision=1859
1 parent 4c553a5 commit 122eb6a

File tree

4 files changed

+42
-28
lines changed

4 files changed

+42
-28
lines changed

CHANGELOG

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
New entries should be added at the top
1+
2005-11-15 New entries should be added at the top 2005-08-14 Applied
2+
Jouni K Steppanen's boxplot patch SF patch#1349997 - JDH
23

34
2005-11-08 Added Nicolas' irregularly spaced image patch
45

examples/widgets/span_selector.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from matplotlib.widgets import SpanSelector
1010

1111
fig = pylab.figure(figsize=(8,6))
12-
ax = fig.add_subplot(111, axisbg='#FFFFCC')
12+
ax = fig.add_subplot(211, axisbg='#FFFFCC')
1313

1414
x,y = 4*(pylab.rand(2,100)-.5)
1515
ax.plot(x,y,'o')
@@ -25,4 +25,7 @@ def onselect(vmin, vmax):
2525
span = SpanSelector(ax, onselect, 'horizontal', useblit=False,
2626
rectprops=dict(alpha=0.5, facecolor='red') )
2727

28+
29+
ax2 = fig.add_subplot(212)
30+
ax2.plot([1,2,3])
2831
pylab.show()

lib/matplotlib/axes.py

Lines changed: 34 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -998,9 +998,11 @@ def bar(self, left, height, width=0.8, bottom=0,
998998
self.autoscale_view()
999999
return patches
10001000

1001-
def boxplot(self, x, notch=0, sym='b+', vert=1, whis=1.5):
1001+
def boxplot(self, x, notch=0, sym='b+', vert=1, whis=1.5,
1002+
positions=None, widths=None):
10021003
"""
1003-
boxplot(x, notch=0, sym='+', vert=1, whis=1.5)
1004+
boxplot(x, notch=0, sym='+', vert=1, whis=1.5,
1005+
positions=None, widths=None)
10041006
10051007
Make a box and whisker plot for each column of x.
10061008
The box extends from the lower to upper quartile values
@@ -1022,6 +1024,14 @@ def boxplot(self, x, notch=0, sym='b+', vert=1, whis=1.5):
10221024
a function of the inner quartile range. They extend to the
10231025
most extreme data point within ( whis*(75%-25%) ) data range.
10241026
1027+
positions (default 1,2,...,n) sets the horizontal positions of
1028+
the boxes. The ticks and limits are automatically set to match
1029+
the positions.
1030+
1031+
widths is either a scalar or a vector and sets the width of
1032+
each box. The default is 0.5, or 0.15*(distance between extreme
1033+
positions) if that is smaller.
1034+
10251035
x is a Numeric array
10261036
10271037
Returns a list of the lines added
@@ -1040,13 +1050,18 @@ def boxplot(self, x, notch=0, sym='b+', vert=1, whis=1.5):
10401050
row, col = x.shape
10411051

10421052
# get some plot info
1043-
num_plots = range(1, col + 1)
1044-
box_width = col * min(0.15, 0.5/col)
1053+
if positions is None:
1054+
positions = range(1, col + 1)
1055+
if widths is None:
1056+
distance = max(positions) - min(positions)
1057+
widths = distance * min(0.15, 0.5/distance)
1058+
if isinstance(widths, float) or isinstance(widths, int):
1059+
widths = ones((col,), 'd') * widths
10451060

10461061
# loop through columns, adding each to plot
10471062
self.hold(True)
1048-
for i in num_plots:
1049-
d = x[:,i-1]
1063+
for i,pos in enumerate(positions):
1064+
d = x[:,i]
10501065
# get median and quartiles
10511066
q1, med, q3 = prctile(d,[25,50,75])
10521067
# get high extreme
@@ -1072,17 +1087,17 @@ def boxplot(self, x, notch=0, sym='b+', vert=1, whis=1.5):
10721087
if len(sym) != 0:
10731088
flier_hi = compress( d > wisk_hi, d )
10741089
flier_lo = compress( d < wisk_lo, d )
1075-
flier_hi_x = ones(flier_hi.shape[0]) * i
1076-
flier_lo_x = ones(flier_lo.shape[0]) * i
1090+
flier_hi_x = ones(flier_hi.shape[0]) * pos
1091+
flier_lo_x = ones(flier_lo.shape[0]) * pos
10771092

10781093
# get x locations for fliers, whisker, whisker cap and box sides
1079-
box_x_min = i - box_width * 0.5
1080-
box_x_max = i + box_width * 0.5
1094+
box_x_min = pos - widths[i] * 0.5
1095+
box_x_max = pos + widths[i] * 0.5
10811096

1082-
wisk_x = ones(2) * i
1097+
wisk_x = ones(2) * pos
10831098

1084-
cap_x_min = i - box_width * 0.25
1085-
cap_x_max = i + box_width * 0.25
1099+
cap_x_min = pos - widths[i] * 0.25
1100+
cap_x_max = pos + widths[i] * 0.25
10861101
cap_x = [cap_x_min, cap_x_max]
10871102

10881103
# get y location for median
@@ -1136,12 +1151,14 @@ def boxplot(self, x, notch=0, sym='b+', vert=1, whis=1.5):
11361151

11371152
# fix our axes/ticks up a little
11381153
if 1 == vert:
1139-
self.set_xlim([0.5, 0.5+col])
1140-
self.set_xticks(num_plots)
1154+
setticks, setlim = self.set_xticks, self.set_xlim
11411155
else:
1142-
self.set_ylim([0.5, 0.5+col])
1143-
self.set_yticks(num_plots)
1156+
setticks, setlim = self.set_yticks, self.set_ylim
11441157

1158+
newlimits = min(positions)-0.5, max(positions)+0.5
1159+
setlim(newlimits)
1160+
setticks(positions)
1161+
11451162
# reset hold status
11461163
self.hold(holdStatus)
11471164

@@ -2112,8 +2129,6 @@ def panx(self, numsteps):
21122129
'Pan the x axis numsteps (plus pan right, minus pan left)'
21132130
self.xaxis.pan(numsteps)
21142131
xmin, xmax = self.viewLim.intervalx().get_bounds()
2115-
for line in self.lines:
2116-
line.set_xclip(xmin, xmax)
21172132
self._send_xlim_event()
21182133

21192134
def pany(self, numsteps):
@@ -3630,8 +3645,6 @@ def zoomx(self, numsteps):
36303645
'Zoom in on the x xaxis numsteps (plus for zoom in, minus for zoom out)'
36313646
self.xaxis.zoom(numsteps)
36323647
xmin, xmax = self.viewLim.intervalx().get_bounds()
3633-
for line in self.lines:
3634-
line.set_xclip(xmin, xmax)
36353648
self._send_xlim_event()
36363649

36373650
def zoomy(self, numsteps):

src/_gtkagg.cpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,10 @@ class _gtkagg_module : public Py::ExtensionModule<_gtkagg_module>
3737
// to gtk. If bbox is not None, blit only the region defined by
3838
// the bbox
3939
args.verify_length(3);
40-
41-
40+
4241
PyGObject *py_drawable = (PyGObject *)(args[0].ptr());
4342
RendererAgg* aggRenderer = static_cast<RendererAgg*>(args[1].ptr());
4443

45-
4644
GdkDrawable *drawable = GDK_DRAWABLE(py_drawable->obj);
4745
GdkGC* gc = gdk_gc_new(drawable);
4846

@@ -61,6 +59,7 @@ class _gtkagg_module : public Py::ExtensionModule<_gtkagg_module>
6159
bool needfree = false;
6260

6361
agg::int8u *destbuffer = NULL;
62+
6463
if (args[2].ptr() == Py_None) {
6564
//bbox is None; copy the entire image
6665
destbuffer = aggRenderer->pixBuffer;
@@ -98,7 +97,6 @@ class _gtkagg_module : public Py::ExtensionModule<_gtkagg_module>
9897
renderer_base destrb(destpf);
9998
//destrb.clear(agg::rgba(1, 0, 0));
10099

101-
//std::cout << "rect " << r << " " << srcheight << " " << b << " ";
102100
agg::rect_base<int> region(destx, desty, (int)r, srcheight-(int)b);
103101
destrb.copy_from(*aggRenderer->renderingBuffer, &region,
104102
-destx, -desty);
@@ -122,7 +120,6 @@ class _gtkagg_module : public Py::ExtensionModule<_gtkagg_module>
122120

123121
if (needfree) delete [] destbuffer;
124122

125-
126123
return Py::Object();
127124

128125
}

0 commit comments

Comments
 (0)