X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fbox-whisker.c;h=2600e8aa6c6d5b02b17155a5ada939683f3b3a20;hb=46cc6dd316280579f5b03dfd39d01bc7daf88df7;hp=fa52476e8ac7775e1606f431acfb529a2951d613;hpb=4239c455e7b1061b7c960b793f9080e113123845;p=pspp-builds.git diff --git a/src/box-whisker.c b/src/box-whisker.c index fa52476e..2600e8aa 100644 --- a/src/box-whisker.c +++ b/src/box-whisker.c @@ -20,106 +20,77 @@ #include "chart.h" #include +#include "misc.h" -/* Draw a box-and-whiskers plot -*/ - -struct data_stats -{ - double ptile0 ; - double ptile25 ; - double median ; - double ptile75 ; - - double ptile100; - - double outlier ; -}; - - -const struct data_stats stats1 = { - 40, - 45, - 54, - 60, - 70, - - 33 -}; - -const struct data_stats stats2 = { - 30, - 40, - 45, - 54, - 60, - - - 72 -}; - - - - - -static const double y_min = 25; -static const double y_max = 75; -static const double y_tick = 10; +#include "factor_stats.h" +/* Draw a box-and-whiskers plot +*/ -#define min(A,B) ((A>B)?B:A) - - -void draw_box_and_whiskers(struct chart *ch, - double box_centre, const struct data_stats *s, - const char *name); - +/* Draw an outlier on the plot CH + * at CENTRELINE + * The outlier is in (*wvp)[idx] + * If EXTREME is non zero, then consider it to be an extreme + * value + */ +void +draw_outlier(struct chart *ch, double centreline, + struct weighted_value **wvp, + int idx, + short extreme); -static double ordinate_scale; -void -draw_box_whisker_chart(struct chart *ch, const char *title) +void +draw_outlier(struct chart *ch, double centreline, + struct weighted_value **wvp, + int idx, + short extreme + ) { - double d; + char label[10]; - ordinate_scale = fabs(ch->data_top - ch->data_bottom) / fabs(y_max - y_min) ; +#define MARKER_CIRCLE 4 +#define MARKER_STAR 3 + pl_fmarker_r(ch->lp, + centreline, + ch->data_bottom + + (wvp[idx]->v.f - ch->y_min ) * ch->ordinate_scale, + extreme?MARKER_STAR:MARKER_CIRCLE, + 20); - chart_write_title(ch, title); + pl_moverel_r(ch->lp, 10,0); + snprintf(label, 10, "%d", wvp[idx]->case_nos->num); - - /* Move to data bottom-left */ - pl_move_r(ch->lp, - ch->data_left, ch->data_bottom); - - for ( d = y_min; d <= y_max ; d += y_tick ) - { - draw_tick (ch, TICK_ORDINATE, (d - y_min ) * ordinate_scale, "%g", d); - } - - draw_box_and_whiskers(ch, - ch->data_left + 1.0/4.0 * (ch->data_right - ch->data_left) , - &stats1,"Stats1" - ); - - draw_box_and_whiskers(ch, - ch->data_left + 3.0/4.0 * (ch->data_right - ch->data_left), - &stats2,"Stats2" - ); - + pl_alabel_r(ch->lp, 'l', 'c', label); } void -draw_box_and_whiskers(struct chart *ch, - double box_centre, const struct data_stats *s, - const char *name) +boxplot_draw_boxplot(struct chart *ch, + double box_centre, + double box_width, + struct metrics *m, + /* + const double hinge[3], + struct weighted_value **wvp, + int n_data, + */ + const char *name) { + double whisker[2]; + int i; + + + const double *hinge = m->hinge; + struct weighted_value **wvp = m->wvp; + const int n_data = m->n_data; + + const double step = (hinge[2] - hinge[0]) * 1.5; - const double box_width = (ch->data_right - ch->data_left) / 4.0; const double box_left = box_centre - box_width / 2.0; @@ -127,22 +98,32 @@ draw_box_and_whiskers(struct chart *ch, const double box_bottom = - ch->data_bottom + ( s->ptile25 - y_min ) * ordinate_scale; + ch->data_bottom + ( hinge[0] - ch->y_min ) * ch->ordinate_scale; const double box_top = - ch->data_bottom + ( s->ptile75 - y_min ) * ordinate_scale; + ch->data_bottom + ( hinge[2] - ch->y_min ) * ch->ordinate_scale; + whisker[1] = hinge[2]; + whisker[0] = wvp[0]->v.f; - const double iq_range = s->ptile75 - s->ptile25; + for ( i = 0 ; i < n_data ; ++i ) + { + if ( hinge[2] + step > wvp[i]->v.f) + whisker[1] = wvp[i]->v.f; + if ( hinge[0] - step > wvp[i]->v.f) + whisker[0] = wvp[i]->v.f; + + } + + const double bottom_whisker = - ch->data_bottom + (min(s->ptile0,s->ptile25 + iq_range*1.5) - y_min ) * - ordinate_scale; + ch->data_bottom + ( whisker[0] - ch->y_min ) * ch->ordinate_scale; + + const double top_whisker = + ch->data_bottom + ( whisker[1] - ch->y_min ) * ch->ordinate_scale; - const double top_whisker = - ch->data_bottom + (min(s->ptile100,s->ptile75 + iq_range*1.5) - y_min ) * - ordinate_scale; pl_savestate_r(ch->lp); @@ -166,9 +147,9 @@ draw_box_and_whiskers(struct chart *ch, pl_linewidth_r(ch->lp,5); pl_fline_r(ch->lp, box_left, - ch->data_bottom + ( s->median - y_min ) * ordinate_scale, + ch->data_bottom + ( hinge[1] - ch->y_min ) * ch->ordinate_scale, box_right, - ch->data_bottom + ( s->median - y_min ) * ordinate_scale); + ch->data_bottom + ( hinge[1] - ch->y_min ) * ch->ordinate_scale); pl_restorestate_r(ch->lp); @@ -187,6 +168,7 @@ draw_box_and_whiskers(struct chart *ch, top_whisker); + /* Draw centre line. (bottom half) */ pl_fline_r(ch->lp, @@ -198,15 +180,19 @@ draw_box_and_whiskers(struct chart *ch, box_centre, top_whisker, box_centre, box_top); - - /* Draw an outlier */ - pl_fcircle_r(ch->lp, - box_centre, - ch->data_bottom + (s->outlier - y_min ) * ordinate_scale, - 5); - - pl_moverel_r(ch->lp, 10,0); - pl_alabel_r(ch->lp,'l','c',"123"); + /* Draw outliers */ + for ( i = 0 ; i < n_data ; ++i ) + { + if ( wvp[i]->v.f >= hinge[2] + step ) + draw_outlier(ch, box_centre, wvp, i, + ( wvp[i]->v.f > hinge[2] + 2 * step ) + ); + + if ( wvp[i]->v.f <= hinge[0] - step ) + draw_outlier(ch, box_centre, wvp, i, + ( wvp[i]->v.f < hinge[0] - 2 * step ) + ); + } /* Draw tick mark on x axis */ @@ -216,3 +202,34 @@ draw_box_and_whiskers(struct chart *ch, } + + +void +boxplot_draw_yscale(struct chart *ch , double y_max, double y_min) +{ + double y_tick; + double d; + + ch->y_max = y_max; + ch->y_min = y_min; + + y_tick = chart_rounded_tick(fabs(ch->y_max - ch->y_min) / 5.0); + + ch->y_min = (ceil( ch->y_min / y_tick ) - 1.0 ) * y_tick; + + ch->y_max = ( floor( ch->y_max / y_tick ) + 1.0 ) * y_tick; + + ch->ordinate_scale = fabs(ch->data_top - ch->data_bottom) + / fabs(ch->y_max - ch->y_min) ; + + + /* Move to data bottom-left */ + pl_move_r(ch->lp, + ch->data_left, ch->data_bottom); + + for ( d = ch->y_min; d <= ch->y_max ; d += y_tick ) + { + draw_tick (ch, TICK_ORDINATE, (d - ch->y_min ) * ch->ordinate_scale, "%g", d); + } + +}