+static void
+show_extremes(struct variable **dependent_var, int n_dep_var,
+ const struct factor *fctr, int n_extremities)
+{
+ int i;
+ int heading_columns ;
+ int n_cols;
+ const int heading_rows = 1;
+ struct tab_table *tbl;
+
+ int n_factors = 1;
+ int n_rows ;
+
+ if ( fctr )
+ {
+ heading_columns = 2;
+ n_factors = hsh_count(fctr->fstats);
+
+ n_rows = n_dep_var * 2 * n_extremities * n_factors;
+
+ if ( fctr->indep_var[1] )
+ heading_columns = 3;
+ }
+ else
+ {
+ heading_columns = 1;
+ n_rows = n_dep_var * 2 * n_extremities;
+ }
+
+ n_rows += heading_rows;
+
+ heading_columns += 2;
+ n_cols = heading_columns + 2;
+
+ tbl = tab_create (n_cols,n_rows,0);
+ tab_headers (tbl, heading_columns, 0, heading_rows, 0);
+
+ tab_dim (tbl, tab_natural_dimensions);
+
+ /* Outline the box, No internal lines*/
+ tab_box (tbl,
+ TAL_2, TAL_2,
+ -1, -1,
+ 0, 0,
+ n_cols - 1, n_rows - 1);
+
+ tab_hline (tbl, TAL_2, 0, n_cols - 1, heading_rows );
+
+ tab_title (tbl, 0, _("Extreme Values"));
+
+ tab_vline (tbl, TAL_2, n_cols - 2, 0, n_rows -1);
+ tab_vline (tbl, TAL_1, n_cols - 1, 0, n_rows -1);
+
+ if ( fctr )
+ {
+ tab_text (tbl, 1, heading_rows - 1, TAB_CENTER | TAT_TITLE,
+ var_to_string(fctr->indep_var[0]));
+
+ if ( fctr->indep_var[1] )
+ tab_text (tbl, 2, heading_rows - 1, TAB_CENTER | TAT_TITLE,
+ var_to_string(fctr->indep_var[1]));
+ }
+
+ tab_text (tbl, n_cols - 1, 0, TAB_CENTER | TAT_TITLE, _("Value"));
+ tab_text (tbl, n_cols - 2, 0, TAB_CENTER | TAT_TITLE, _("Case Number"));
+
+ for ( i = 0 ; i < n_dep_var ; ++i )
+ {
+
+ if ( i > 0 )
+ tab_hline(tbl, TAL_1, 0, n_cols -1 ,
+ i * 2 * n_extremities * n_factors + heading_rows);
+
+ tab_text (tbl, 0,
+ i * 2 * n_extremities * n_factors + heading_rows,
+ TAB_LEFT | TAT_TITLE,
+ var_to_string(dependent_var[i])
+ );
+
+
+ if ( !fctr )
+ populate_extremes(tbl, heading_columns - 2,
+ i * 2 * n_extremities * n_factors + heading_rows,
+ n_extremities, &totals[i]);
+
+ else
+ {
+ struct factor_statistics **fs = fctr->fs;
+ int count = 0 ;
+
+ while (*fs)
+ {
+ static union value prev ;
+
+ const int row = heading_rows + ( 2 * n_extremities ) *
+ ( ( i * n_factors ) + count );
+
+
+ if ( 0 != compare_values(&prev, &(*fs)->id[0],
+ fctr->indep_var[0]->width))
+ {
+
+ if ( count > 0 )
+ tab_hline (tbl, TAL_1, 1, n_cols - 1, row);
+
+ tab_text (tbl,
+ 1, row,
+ TAB_LEFT | TAT_TITLE,
+ value_to_string(&(*fs)->id[0], fctr->indep_var[0])
+ );
+ }
+
+ prev = (*fs)->id[0];
+
+ if (fctr->indep_var[1] && count > 0 )
+ tab_hline(tbl, TAL_1, 2, n_cols - 1, row);
+
+ if ( fctr->indep_var[1])
+ tab_text (tbl, 2, row,
+ TAB_LEFT | TAT_TITLE,
+ value_to_string(&(*fs)->id[1], fctr->indep_var[1])
+ );
+
+ populate_extremes(tbl, heading_columns - 2,
+ row, n_extremities,
+ &(*fs)->m[i]);
+
+ count++ ;
+ fs++;
+ }
+ }
+ }
+
+ tab_submit(tbl);
+}
+
+
+
+/* Fill in the extremities table */
+void
+populate_extremes(struct tab_table *t,
+ int col, int row, int n, const struct metrics *m)
+{
+ int extremity;
+ int idx=0;
+
+
+ tab_text(t, col, row,
+ TAB_RIGHT | TAT_TITLE ,
+ _("Highest")
+ );
+
+ tab_text(t, col, row + n ,
+ TAB_RIGHT | TAT_TITLE ,
+ _("Lowest")
+ );
+
+
+ tab_hline(t, TAL_1, col, col + 3, row + n );
+
+ for (extremity = 0; extremity < n ; ++extremity )
+ {
+ /* Highest */
+ tab_float(t, col + 1, row + extremity,
+ TAB_RIGHT,
+ extremity + 1, 8, 0);
+
+
+ /* Lowest */
+ tab_float(t, col + 1, row + extremity + n,
+ TAB_RIGHT,
+ extremity + 1, 8, 0);
+
+ }
+
+
+ /* Lowest */
+ for (idx = 0, extremity = 0; extremity < n && idx < m->n_data ; ++idx )
+ {
+ int j;
+ const struct weighted_value *wv = m->wvp[idx];
+ struct case_node *cn = wv->case_nos;
+
+
+ for (j = 0 ; j < wv->w ; ++j )
+ {
+ if ( extremity + j >= n )
+ break ;
+
+ tab_float(t, col + 3, row + extremity + j + n,
+ TAB_RIGHT,
+ wv->v.f, 8, 2);
+
+ tab_float(t, col + 2, row + extremity + j + n,
+ TAB_RIGHT,
+ cn->num, 8, 0);
+
+ if ( cn->next )
+ cn = cn->next;
+
+ }
+
+ extremity += wv->w ;
+ }
+
+
+ /* Highest */
+ for (idx = m->n_data - 1, extremity = 0; extremity < n && idx >= 0; --idx )
+ {
+ int j;
+ const struct weighted_value *wv = m->wvp[idx];
+ struct case_node *cn = wv->case_nos;
+
+ for (j = 0 ; j < wv->w ; ++j )
+ {
+ if ( extremity + j >= n )
+ break ;
+
+ tab_float(t, col + 3, row + extremity + j,
+ TAB_RIGHT,
+ wv->v.f, 8, 2);
+
+ tab_float(t, col + 2, row + extremity + j,
+ TAB_RIGHT,
+ cn->num, 8, 0);
+
+ if ( cn->next )
+ cn = cn->next;
+
+ }
+
+ extremity += wv->w ;
+ }
+}
+
+
+/* Show the descriptives table */
+void
+show_descriptives(struct variable **dependent_var,
+ int n_dep_var,
+ struct factor *fctr)
+{
+ int i;
+ int heading_columns ;
+ int n_cols;
+ const int n_stat_rows = 13;
+
+ const int heading_rows = 1;
+
+ struct tab_table *tbl;
+
+ int n_factors = 1;
+ int n_rows ;
+
+ if ( fctr )
+ {
+ heading_columns = 4;
+ n_factors = hsh_count(fctr->fstats);
+
+ n_rows = n_dep_var * n_stat_rows * n_factors;
+
+ if ( fctr->indep_var[1] )
+ heading_columns = 5;
+ }
+ else
+ {
+ heading_columns = 3;
+ n_rows = n_dep_var * n_stat_rows;
+ }
+
+ n_rows += heading_rows;
+
+ n_cols = heading_columns + 2;
+
+
+ tbl = tab_create (n_cols, n_rows, 0);
+
+ tab_headers (tbl, heading_columns + 1, 0, heading_rows, 0);
+
+ tab_dim (tbl, tab_natural_dimensions);
+
+ /* Outline the box and have no internal lines*/
+ tab_box (tbl,
+ TAL_2, TAL_2,
+ -1, -1,
+ 0, 0,
+ n_cols - 1, n_rows - 1);
+
+ tab_hline (tbl, TAL_2, 0, n_cols - 1, heading_rows );
+
+ tab_vline (tbl, TAL_1, heading_columns, 0, n_rows - 1);
+ tab_vline (tbl, TAL_2, n_cols - 2, 0, n_rows - 1);
+ tab_vline (tbl, TAL_1, n_cols - 1, 0, n_rows - 1);
+
+ tab_text (tbl, n_cols - 2, 0, TAB_CENTER | TAT_TITLE, _("Statistic"));
+ tab_text (tbl, n_cols - 1, 0, TAB_CENTER | TAT_TITLE, _("Std. Error"));
+
+ tab_title (tbl, 0, _("Descriptives"));
+
+
+ for ( i = 0 ; i < n_dep_var ; ++i )
+ {
+ const int row = heading_rows + i * n_stat_rows * n_factors ;
+
+ if ( i > 0 )
+ tab_hline(tbl, TAL_1, 0, n_cols - 1, row );
+
+ tab_text (tbl, 0,
+ i * n_stat_rows * n_factors + heading_rows,
+ TAB_LEFT | TAT_TITLE,
+ var_to_string(dependent_var[i])
+ );
+
+
+ if ( fctr )
+ {
+ struct factor_statistics **fs = fctr->fs;
+ int count = 0;
+
+ tab_text (tbl, 1, heading_rows - 1, TAB_CENTER | TAT_TITLE,
+ var_to_string(fctr->indep_var[0]));
+
+
+ if ( fctr->indep_var[1])
+ tab_text (tbl, 2, heading_rows - 1, TAB_CENTER | TAT_TITLE,
+ var_to_string(fctr->indep_var[1]));
+
+ while( *fs )
+ {
+
+ static union value prev ;
+
+ const int row = heading_rows + n_stat_rows *
+ ( ( i * n_factors ) + count );
+
+
+ if ( 0 != compare_values(&prev, &(*fs)->id[0],
+ fctr->indep_var[0]->width))
+ {
+
+ if ( count > 0 )
+ tab_hline (tbl, TAL_1, 1, n_cols - 1, row);
+
+ tab_text (tbl,
+ 1, row,
+ TAB_LEFT | TAT_TITLE,
+ value_to_string(&(*fs)->id[0], fctr->indep_var[0])
+ );
+ }
+
+ prev = (*fs)->id[0];
+
+ if (fctr->indep_var[1] && count > 0 )
+ tab_hline(tbl, TAL_1, 2, n_cols - 1, row);
+
+ if ( fctr->indep_var[1])
+ tab_text (tbl, 2, row,
+ TAB_LEFT | TAT_TITLE,
+ value_to_string(&(*fs)->id[1], fctr->indep_var[1])
+ );
+
+ populate_descriptives(tbl, heading_columns - 2,
+ row, &(*fs)->m[i]);
+
+ count++ ;
+ fs++;
+ }
+
+ }
+
+ else
+ {
+
+ populate_descriptives(tbl, heading_columns - 2,
+ i * n_stat_rows * n_factors + heading_rows,
+ &totals[i]);
+ }
+ }
+
+ tab_submit(tbl);
+
+}
+
+
+
+
+/* Fill in the descriptives data */
+void
+populate_descriptives(struct tab_table *tbl, int col, int row,
+ const struct metrics *m)
+{
+
+ const double t = gsl_cdf_tdist_Qinv(1 - cmd.n_cinterval[0]/100.0/2.0, \
+ m->n -1);
+
+
+ tab_text (tbl, col,
+ row,
+ TAB_LEFT | TAT_TITLE,
+ _("Mean"));
+
+ tab_float (tbl, col + 2,
+ row,
+ TAB_CENTER,
+ m->mean,
+ 8,2);
+
+ tab_float (tbl, col + 3,
+ row,
+ TAB_CENTER,
+ m->se_mean,
+ 8,3);
+
+
+ tab_text (tbl, col,
+ row + 1,
+ TAB_LEFT | TAT_TITLE | TAT_PRINTF,
+ _("%g%% Confidence Interval for Mean"), cmd.n_cinterval[0]);
+
+
+ tab_text (tbl, col + 1,
+ row + 1,
+ TAB_LEFT | TAT_TITLE,
+ _("Lower Bound"));
+
+ tab_float (tbl, col + 2,
+ row + 1,
+ TAB_CENTER,
+ m->mean - t * m->se_mean,
+ 8,3);
+
+ tab_text (tbl, col + 1,
+ row + 2,
+ TAB_LEFT | TAT_TITLE,
+ _("Upper Bound"));
+
+
+ tab_float (tbl, col + 2,
+ row + 2,
+ TAB_CENTER,
+ m->mean + t * m->se_mean,
+ 8,3);
+
+ tab_text (tbl, col,
+ row + 3,
+ TAB_LEFT | TAT_TITLE,
+ _("5% Trimmed Mean"));
+
+ tab_float (tbl, col + 2,
+ row + 3,
+ TAB_CENTER,
+ m->trimmed_mean,
+ 8,2);
+
+ tab_text (tbl, col,
+ row + 4,
+ TAB_LEFT | TAT_TITLE,
+ _("Median"));
+
+ {
+ struct percentile *p;
+ double d = 50;
+
+ p = hsh_find(m->ptile_hash, &d);
+
+ assert(p);
+
+ tab_float (tbl, col + 2,
+ row + 4,
+ TAB_CENTER,
+ p->v,
+ 8, 2);
+ }
+
+ tab_text (tbl, col,
+ row + 5,
+ TAB_LEFT | TAT_TITLE,
+ _("Variance"));
+
+ tab_float (tbl, col + 2,
+ row + 5,
+ TAB_CENTER,
+ m->var,
+ 8,3);
+
+
+ tab_text (tbl, col,
+ row + 6,
+ TAB_LEFT | TAT_TITLE,
+ _("Std. Deviation"));
+
+
+ tab_float (tbl, col + 2,
+ row + 6,
+ TAB_CENTER,
+ m->stddev,
+ 8,3);
+
+
+ tab_text (tbl, col,
+ row + 7,
+ TAB_LEFT | TAT_TITLE,
+ _("Minimum"));
+
+ tab_float (tbl, col + 2,
+ row + 7,
+ TAB_CENTER,
+ m->min,
+ 8,3);
+
+ tab_text (tbl, col,
+ row + 8,
+ TAB_LEFT | TAT_TITLE,
+ _("Maximum"));
+
+ tab_float (tbl, col + 2,
+ row + 8,
+ TAB_CENTER,
+ m->max,
+ 8,3);
+
+
+ tab_text (tbl, col,
+ row + 9,
+ TAB_LEFT | TAT_TITLE,
+ _("Range"));
+
+
+ tab_float (tbl, col + 2,
+ row + 9,
+ TAB_CENTER,
+ m->max - m->min,
+ 8,3);
+
+ tab_text (tbl, col,
+ row + 10,
+ TAB_LEFT | TAT_TITLE,
+ _("Interquartile Range"));
+
+ {
+ struct percentile *p1;
+ struct percentile *p2;
+
+ double d = 75;
+ p1 = hsh_find(m->ptile_hash, &d);
+
+ d = 25;
+ p2 = hsh_find(m->ptile_hash, &d);
+
+ assert(p1);
+ assert(p2);
+
+ tab_float (tbl, col + 2,
+ row + 10,
+ TAB_CENTER,
+ p1->v - p2->v,
+ 8, 2);
+ }
+
+
+
+ tab_text (tbl, col,
+ row + 11,
+ TAB_LEFT | TAT_TITLE,
+ _("Skewness"));
+
+
+ tab_float (tbl, col + 2,
+ row + 11,
+ TAB_CENTER,
+ m->skewness,
+ 8,3);
+
+ /* stderr of skewness */
+ tab_float (tbl, col + 3,
+ row + 11,
+ TAB_CENTER,
+ calc_seskew(m->n),
+ 8,3);
+
+
+ tab_text (tbl, col,
+ row + 12,
+ TAB_LEFT | TAT_TITLE,
+ _("Kurtosis"));
+