1 /* PSPP - computes sample statistics.
2 Copyright (C) 2004 Free Software Foundation, Inc.
3 Written by John Darrington <john@darrington.wattle.id.au>
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
24 /* Draw a box-and-whiskers plot
40 const struct data_stats stats1 = {
50 const struct data_stats stats2 = {
65 static const double y_min = 25;
66 static const double y_max = 75;
67 static const double y_tick = 10;
71 #define min(A,B) ((A>B)?B:A)
74 void draw_box_and_whiskers(struct chart *ch,
75 double box_centre, const struct data_stats *s,
79 static double ordinate_scale;
82 draw_box_whisker_chart(struct chart *ch, const char *title)
86 ordinate_scale = fabs(ch->data_top - ch->data_bottom) / fabs(y_max - y_min) ;
89 chart_write_title(ch, title);
93 /* Move to data bottom-left */
95 ch->data_left, ch->data_bottom);
97 for ( d = y_min; d <= y_max ; d += y_tick )
99 draw_tick (ch, TICK_ORDINATE, (d - y_min ) * ordinate_scale, "%g", d);
102 draw_box_and_whiskers(ch,
103 ch->data_left + 1.0/4.0 * (ch->data_right - ch->data_left) ,
107 draw_box_and_whiskers(ch,
108 ch->data_left + 3.0/4.0 * (ch->data_right - ch->data_left),
117 draw_box_and_whiskers(struct chart *ch,
118 double box_centre, const struct data_stats *s,
122 const double box_width = (ch->data_right - ch->data_left) / 4.0;
124 const double box_left = box_centre - box_width / 2.0;
126 const double box_right = box_centre + box_width / 2.0;
129 const double box_bottom =
130 ch->data_bottom + ( s->ptile25 - y_min ) * ordinate_scale;
133 const double box_top =
134 ch->data_bottom + ( s->ptile75 - y_min ) * ordinate_scale;
137 const double iq_range = s->ptile75 - s->ptile25;
139 const double bottom_whisker =
140 ch->data_bottom + (min(s->ptile0,s->ptile25 + iq_range*1.5) - y_min ) *
143 const double top_whisker =
144 ch->data_bottom + (min(s->ptile100,s->ptile75 + iq_range*1.5) - y_min ) *
147 pl_savestate_r(ch->lp);
151 pl_savestate_r(ch->lp);
152 pl_fillcolorname_r(ch->lp,ch->fill_colour);
153 pl_filltype_r(ch->lp,1);
160 pl_restorestate_r(ch->lp);
164 /* Draw the median */
165 pl_savestate_r(ch->lp);
166 pl_linewidth_r(ch->lp,5);
169 ch->data_bottom + ( s->median - y_min ) * ordinate_scale,
171 ch->data_bottom + ( s->median - y_min ) * ordinate_scale);
172 pl_restorestate_r(ch->lp);
175 /* Draw the bottom whisker */
182 /* Draw top whisker */
193 box_centre, bottom_whisker,
194 box_centre, box_bottom);
198 box_centre, top_whisker,
199 box_centre, box_top);
202 /* Draw an outlier */
205 ch->data_bottom + (s->outlier - y_min ) * ordinate_scale,
208 pl_moverel_r(ch->lp, 10,0);
209 pl_alabel_r(ch->lp,'l','c',"123");
212 /* Draw tick mark on x axis */
213 draw_tick(ch, TICK_ABSCISSA, box_centre - ch->data_left, name);
215 pl_restorestate_r(ch->lp);