From: Ben Pfaff Date: Thu, 31 Dec 2020 19:07:31 +0000 (-0800) Subject: pivot-output: Replicate dimension headings when divided by vertical rules. X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?p=pspp;a=commitdiff_plain;h=d59763f59e0b5cc5da18161f3049619748fbd087 pivot-output: Replicate dimension headings when divided by vertical rules. This introduces a comment into compose_headings() that explains the problem that it fixes. --- diff --git a/src/output/pivot-output.c b/src/output/pivot-output.c index 7d5ee7a9fc..6f92f87c96 100644 --- a/src/output/pivot-output.c +++ b/src/output/pivot-output.c @@ -44,7 +44,9 @@ find_category (const struct pivot_dimension *d, int dim_index, for (const struct pivot_category *c = d->presentation_leaves[index]; c; c = c->parent) { - if (!row_ofs) + /* A category can covert multiple rows. Only return the category for its + top row. */ + if (row_ofs == c->extra_depth) return c; row_ofs -= 1 + c->extra_depth; @@ -213,9 +215,60 @@ compose_headings (struct table *t, if (!a_axis->n_dimensions || !n_columns || !b_size) return; - int bottom_row = b_size - 1; const int stride = MAX (1, a_axis->n_dimensions); - for (int dim_index = 0; dim_index < a_axis->n_dimensions; dim_index++) + + /* Below, we're going to iterate through the dimensions. Each dimension + occupies one or more rows in the heading. 'top_row' is the top row of + these (and 'top_row + d->label_depth - 1' is the bottom row). */ + int top_row = 0; + + /* We're going to iterate through dimensions and the rows that label them + from top to bottom (from outer to inner dimensions). As we move downward, + we start drawing vertical rules to separate categories and groups. After + we start drawing a vertical rule in a particular horizontal position, it + continues until the bottom of the heading. vrules[pos] indicates whether, + in our current row, we have already started drawing a vertical rule in + horizontal position 'pos'. (There are n_columns + 1 horizontal positions. + We allocate all of them for convenience below but only the inner n_columns + - 1 of them really matter.) + + Here's an example that shows how vertical rules continue all the way + downward: + + +-----------------------------------------------------+ __ + | bbbb | | + +-----------------+-----------------+-----------------+ |dimension "bbbb" + | bbbb1 | bbbb2 | bbbb3 | _| + +-----------------+-----------------+-----------------+ __ + | aaaa | aaaa | aaaa | | + +-----+-----+-----+-----+-----+-----+-----+-----+-----+ |dimension "aaaa" + |aaaa1|aaaa2|aaaa3|aaaa1|aaaa2|aaaa3|aaaa1|aaaa2|aaaa3| _| + +-----+-----+-----+-----+-----+-----+-----+-----+-----+ + + ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ + | | | | | | | | | | + 0 1 2 3 4 5 6 7 8 9 + |___________________vrules[] indexes__________________| + + Our data structures are more naturally iterated from bottom to top (inner + to outer dimensions). A previous version of this code actually worked + like that, but it didn't draw all of the vertical lines correctly as shown + above. It ended up rendering the above heading much like shown below, + which isn't what users expect. The "aaaa" label really needs to be shown + three times for clarity: + + +-----------------------------------------------------+ + | bbbb | + +-----------------+-----------------+-----------------+ + | bbbb1 | bbbb2 | bbbb3 | + +-----------------+-----------------+-----------------+ + | | aaaa | | + +-----+-----+-----+-----+-----+-----+-----+-----+-----+ + |aaaa1|aaaa2|aaaa3|aaaa1|aaaa2|aaaa3|aaaa1|aaaa2|aaaa3| + +-----+-----+-----+-----+-----+-----+-----+-----+-----+ + */ + bool *vrules = xzalloc (n_columns + 1); + for (int dim_index = a_axis->n_dimensions; --dim_index >= 0; ) { const struct pivot_dimension *d = a_axis->dimensions[dim_index]; if (d->hide_all_labels) @@ -226,7 +279,8 @@ compose_headings (struct table *t, for (size_t x1 = 0; x1 < n_columns;) { const struct pivot_category *c = find_category ( - d, dim_index, column_enumeration + x1 * stride, row_ofs); + d, dim_index, column_enumeration + x1 * stride, + d->label_depth - row_ofs - 1); if (!c) { x1++; @@ -236,14 +290,17 @@ compose_headings (struct table *t, size_t x2; for (x2 = x1 + 1; x2 < n_columns; x2++) { + if (vrules[x2]) + break; const struct pivot_category *c2 = find_category ( - d, dim_index, column_enumeration + x2 * stride, row_ofs); + d, dim_index, column_enumeration + x2 * stride, + d->label_depth - row_ofs - 1); if (c != c2) break; } - int y1 = bottom_row - row_ofs - c->extra_depth; - int y2 = bottom_row - row_ofs + 1; + int y1 = top_row + row_ofs; + int y2 = top_row + row_ofs + c->extra_depth + 1; bool is_outer_row = y1 == 0; bool is_inner_row = y2 == b_size; if (pivot_category_is_leaf (c) || c->show_label) @@ -267,6 +324,7 @@ compose_headings (struct table *t, : cat_col_vert); draw_line (t, borders, style, b, x2 + a_ofs, y1, t->n[b] - 1); + vrules[x2] = true; } if (pivot_category_is_leaf (c) && x1 > 0) { @@ -276,12 +334,12 @@ compose_headings (struct table *t, : cat_col_vert); draw_line (t, borders, style, b, x1 + a_ofs, y1, t->n[b] - 1); + vrules[x1] = true; } } if (c->parent && c->parent->show_label) draw_line (t, borders, cat_col_horz, a, y1, x1 + a_ofs, x2 + a_ofs - 1); - x1 = x2; } } @@ -291,19 +349,19 @@ compose_headings (struct table *t, int bb[TABLE_N_AXES][2]; bb[a][0] = 0; bb[a][1] = a_ofs - 1; - bb[b][0] = bottom_row - d->label_depth + 1; - bb[b][1] = bottom_row; + bb[b][0] = top_row; + bb[b][1] = top_row + d->label_depth - 1; fill_cell (t, bb[H][0], bb[V][0], bb[H][1], bb[V][1], corner_style, PIVOT_AREA_CORNER, d->root->name, footnotes, show_values, show_variables, false); } if (dim_index > 1) - draw_line (t, borders, dim_col_horz, a, bottom_row + 1, a_ofs, + draw_line (t, borders, dim_col_horz, a, top_row, a_ofs, t->n[a] - 1); - - bottom_row -= d->label_depth; + top_row += d->label_depth; } + free (vrules); } static void diff --git a/tests/language/lexer/variable-parser.at b/tests/language/lexer/variable-parser.at index 2e22934ab3..2591ef276b 100644 --- a/tests/language/lexer/variable-parser.at +++ b/tests/language/lexer/variable-parser.at @@ -55,13 +55,13 @@ Table: X × Yabbadabbadoo ,,,Yabbadabbadoo,,,,,,,Total ,,,1.00,2.00,3.00,4.00,5.00,6.00,7.00, X,1.00,Count,0,0,0,0,0,0,0,0 -,2.00,,0,0,0,0,0,0,0,0 -,3.00,,0,0,0,0,0,0,0,0 -,4.00,,0,0,0,0,1,0,0,1 -,5.00,,0,0,0,0,0,0,0,0 -,6.00,,0,0,0,0,0,0,0,0 -,7.00,,0,0,0,0,0,0,0,0 -Total,,,0,0,0,0,1,0,0,1 +,2.00,Count,0,0,0,0,0,0,0,0 +,3.00,Count,0,0,0,0,0,0,0,0 +,4.00,Count,0,0,0,0,1,0,0,1 +,5.00,Count,0,0,0,0,0,0,0,0 +,6.00,Count,0,0,0,0,0,0,0,0 +,7.00,Count,0,0,0,0,0,0,0,0 +Total,,Count,0,0,0,0,1,0,0,1 ]) AT_CLEANUP diff --git a/tests/language/stats/crosstabs.at b/tests/language/stats/crosstabs.at index de13f1b6b1..91ff4393ee 100644 --- a/tests/language/stats/crosstabs.at +++ b/tests/language/stats/crosstabs.at @@ -44,13 +44,13 @@ Table: X × Y ,,,Y,,,,,,,Total ,,,1.00,2.00,3.00,4.00,5.00,6.00,7.00, X,1.00,Count,0,0,0,0,0,0,0,0 -,2.00,,0,0,0,0,0,0,0,0 -,3.00,,0,0,0,0,0,0,0,0 -,4.00,,0,0,0,0,1,0,0,1 -,5.00,,0,0,0,0,0,0,0,0 -,6.00,,0,0,0,0,0,0,0,0 -,7.00,,0,0,0,0,0,0,0,0 -Total,,,0,0,0,0,1,0,0,1 +,2.00,Count,0,0,0,0,0,0,0,0 +,3.00,Count,0,0,0,0,0,0,0,0 +,4.00,Count,0,0,0,0,1,0,0,1 +,5.00,Count,0,0,0,0,0,0,0,0 +,6.00,Count,0,0,0,0,0,0,0,0 +,7.00,Count,0,0,0,0,0,0,0,0 +Total,,Count,0,0,0,0,1,0,0,1 ]]) AT_CLEANUP @@ -82,9 +82,9 @@ Table: x × y ,,,y,,,,,,,Total ,,,1.00,2.00,3.00,4.00,5.00,6.00,7.00, x,1.00,Count,,,,,,,, -,2.00,,,,,,,,, -,3.00,,,,,,,,, -Total,,,,,,,,,, +,2.00,Count,,,,,,,, +,3.00,Count,,,,,,,, +Total,,Count,,,,,,,, ]]) AT_CLEANUP @@ -124,9 +124,9 @@ Table: x × y ,,,y,,,,Total ,,,one unity,three lots,two duality,zero none, x,1.00,Count,1,0,0,1,2 -,2.00,,0,0,1,0,1 -,3.00,,0,1,0,0,1 -Total,,,1,1,1,1,4 +,2.00,Count,0,0,1,0,1 +,3.00,Count,0,1,0,0,1 +Total,,Count,1,1,1,1,4 ]]) AT_CLEANUP @@ -183,8 +183,8 @@ Table: y × z ,,,z,,Total ,,,1,2, y,1,Count,4,3,7 -,2,,1,1,2 -Total,,,5,4,9 +,2,Count,1,1,2 +Total,,Count,5,4,9 ]) AT_CLEANUP @@ -220,9 +220,9 @@ Table: x × y ,,,y,,Total ,,,1.00,2.00, x,2.00,Count,0,1,1 -,3.00,,1,0,1 -,4.00,,1,1,2 -Total,,,2,2,4 +,3.00,Count,1,0,1 +,4.00,Count,1,1,2 +Total,,Count,2,2,4 Table: Chi-Square Tests ,Value,df,Asymptotic Sig. (2-tailed) @@ -385,16 +385,16 @@ Table: x × y × z ,,,,,y,,Total ,,,,,1,2, z,1,x,1,Count,1,0,1 -,,,3,,0,0,1 -,,,5,,1,0,1 -,,,7,,0,0,1 -,,,8,,0,1,1 -,,Total,,,4,1,5 -,2,x,2,,0,0,1 -,,,4,,0,1,1 -,,,6,,0,0,1 -,,,9,,1,0,1 -,,Total,,,3,1,4 +,,,3,Count,0,0,1 +,,,5,Count,1,0,1 +,,,7,Count,0,0,1 +,,,8,Count,0,1,1 +,,Total,,Count,4,1,5 +,2,x,2,Count,0,0,1 +,,,4,Count,0,1,1 +,,,6,Count,0,0,1 +,,,9,Count,1,0,1 +,,Total,,Count,3,1,4 Table: Chi-Square Tests ,,,Value,df,Asymptotic Sig. (2-tailed) @@ -497,8 +497,8 @@ Table: x × y ,,,y,,Total ,,,1.00,2.00, x,1.00,Count,2.80,3.20,6.00 -,2.00,,1.00,2.00,3.00 -Total,,,3.80,5.20,9.00 +,2.00,Count,1.00,2.00,3.00 +Total,,Count,3.80,5.20,9.00 Table: Summary ,Cases,,,,, @@ -510,8 +510,8 @@ Table: x × y ,,,y,,Total ,,,1.00,2.00, x,1.00,Count,2.80,3.20,6.00 -,2.00,,1.00,2.00,3.00 -Total,,,3.80,5.20,9.00 +,2.00,Count,1.00,2.00,3.00 +Total,,Count,3.80,5.20,9.00 Table: Summary ,Cases,,,,, @@ -523,8 +523,8 @@ Table: x × y ,,,y,,Total ,,,1.00,2.00, x,1.00,Count,2.00,4.00,6.00 -,2.00,,1.00,2.00,3.00 -Total,,,3.00,6.00,9.00 +,2.00,Count,1.00,2.00,3.00 +Total,,Count,3.00,6.00,9.00 Table: Summary ,Cases,,,,, @@ -536,8 +536,8 @@ Table: x × y ,,,y,,Total ,,,1.00,2.00, x,1.00,Count,2.00,2.00,4.00 -,2.00,,1.00,2.00,3.00 -Total,,,3.00,4.00,7.00 +,2.00,Count,1.00,2.00,3.00 +Total,,Count,3.00,4.00,7.00 Table: Summary ,Cases,,,,, @@ -549,8 +549,8 @@ Table: x × y ,,,y,,Total ,,,1.00,2.00, x,1.00,Count,3.00,3.00,6.00 -,2.00,,1.00,2.00,3.00 -Total,,,4.00,5.00,9.00 +,2.00,Count,1.00,2.00,3.00 +Total,,Count,4.00,5.00,9.00 Table: Summary ,Cases,,,,, @@ -562,8 +562,8 @@ Table: x × y ,,,y,,Total ,,,1.00,2.00, x,1.00,Count,2.00,3.00,5.00 -,2.00,,1.00,2.00,3.00 -Total,,,3.00,5.00,8.00 +,2.00,Count,1.00,2.00,3.00 +Total,,Count,3.00,5.00,8.00 ]) AT_CLEANUP @@ -596,9 +596,9 @@ Table: x × y ,,,y,,Total ,,,2.00,1.00, x,4.00,Count,0,1,1 -,3.00,,2,1,3 -,2.00,,2,0,2 -Total,,,4,2,6 +,3.00,Count,2,1,3 +,2.00,Count,2,0,2 +Total,,Count,4,2,6 ]) AT_CLEANUP @@ -858,8 +858,8 @@ Table: type of school × female ,,,female,,Total ,,,male,female, type of school,public,Count,77,91,168 -,private,,14,18,32 -Total,,,91,109,200 +,private,Count,14,18,32 +Total,,Count,91,109,200 Table: Chi-Square Tests ,Value,df,Asymptotic Sig. (2-tailed),Exact Sig. (2-tailed),Exact Sig. (1-tailed) @@ -880,8 +880,8 @@ Table: female × ses ,,,ses,,,Total ,,,low,middle,high, female,male,Count,15,47,29,91 -,female,,32,48,29,109 -Total,,,47,95,58,200 +,female,Count,32,48,29,109 +Total,,Count,47,95,58,200 Table: Chi-Square Tests ,Value,df,Asymptotic Sig. (2-tailed) @@ -920,10 +920,10 @@ Table: x × y ,,,y,,,,,Total ,,,4.000,6.000,10.000,12.000,13.000, x,1.000,Count,1,0,0,0,0,1 -,3.000,,0,1,0,0,0,1 -,5.000,,0,0,1,1,0,2 -,6.000,,0,0,0,0,1,1 -Total,,,1,1,1,1,1,5 +,3.000,Count,0,1,0,0,0,1 +,5.000,Count,0,0,1,1,0,2 +,6.000,Count,0,0,0,0,1,1 +Total,,Count,1,1,1,1,1,5 Table: Symmetric Measures ,,Value,Asymp. Std. Error,Approx. T @@ -965,16 +965,16 @@ Table: x × y ,,,y,,,,,,,,,Total ,,,1.500,4.000,5.000,6.000,6.500,7.000,9.000,10.500,11.000, x,1.000,Count,1,0,0,0,0,0,0,0,0,1 -,2.000,,1,0,0,0,0,0,0,0,0,1 -,3.000,,0,1,0,0,0,0,0,0,0,1 -,4.000,,0,0,0,1,0,0,0,0,0,1 -,5.000,,0,0,1,0,0,0,0,0,0,1 -,6.000,,0,0,0,0,0,1,0,0,0,1 -,7.000,,0,0,0,0,1,0,0,0,0,1 -,8.000,,0,0,0,0,0,0,1,0,0,1 -,9.000,,0,0,0,0,0,0,0,1,0,1 -,10.000,,0,0,0,0,0,0,0,0,1,1 -Total,,,2,1,1,1,1,1,1,1,1,10 +,2.000,Count,1,0,0,0,0,0,0,0,0,1 +,3.000,Count,0,1,0,0,0,0,0,0,0,1 +,4.000,Count,0,0,0,1,0,0,0,0,0,1 +,5.000,Count,0,0,1,0,0,0,0,0,0,1 +,6.000,Count,0,0,0,0,0,1,0,0,0,1 +,7.000,Count,0,0,0,0,1,0,0,0,0,1 +,8.000,Count,0,0,0,0,0,0,1,0,0,1 +,9.000,Count,0,0,0,0,0,0,0,1,0,1 +,10.000,Count,0,0,0,0,0,0,0,0,1,1 +Total,,Count,2,1,1,1,1,1,1,1,1,10 Table: Symmetric Measures ,,Value,Asymp. Std. Error,Approx. T @@ -1015,13 +1015,13 @@ Table: x × y ,,,y,,,,,,,,Total ,,,28.000,58.000,66.000,75.000,85.000,87.000,91.000,122.000, x,25.000,Count,1,0,0,0,0,0,0,0,1 -,35.000,,0,1,0,0,0,0,0,0,1 -,44.000,,0,0,1,0,0,0,0,0,1 -,50.000,,0,0,0,1,0,0,0,0,1 -,56.000,,0,0,0,0,0,1,1,0,2 -,65.000,,0,0,0,0,1,0,1,0,2 -,87.000,,0,0,0,0,0,0,0,1,1 -Total,,,1,1,1,1,1,1,2,1,9 +,35.000,Count,0,1,0,0,0,0,0,0,1 +,44.000,Count,0,0,1,0,0,0,0,0,1 +,50.000,Count,0,0,0,1,0,0,0,0,1 +,56.000,Count,0,0,0,0,0,1,1,0,2 +,65.000,Count,0,0,0,0,1,0,1,0,2 +,87.000,Count,0,0,0,0,0,0,0,1,1 +Total,,Count,1,1,1,1,1,1,2,1,9 Table: Symmetric Measures ,,Value,Asymp. Std. Error,Approx. T @@ -1065,15 +1065,15 @@ Table: x × y ,,,y,,,,,,,,,,,,Total ,,,2.000,4.000,5.000,7.000,9.000,11.000,12.000,14.000,15.000,17.000,18.000,20.000, x,2.000,Count,0,0,0,1,0,0,0,0,0,0,0,0,1 -,3.000,,0,0,0,0,0,0,1,0,0,0,0,0,1 -,4.000,,0,0,0,0,1,1,0,0,0,0,0,0,2 -,5.000,,0,0,1,0,0,0,0,0,0,0,0,0,1 -,6.000,,1,1,0,0,0,0,0,0,0,0,0,0,2 -,7.000,,0,0,0,0,0,0,0,1,0,0,0,0,1 -,8.000,,0,0,0,0,0,0,0,0,1,0,0,0,1 -,9.000,,0,0,0,0,0,0,0,0,0,1,0,0,1 -,10.000,,0,0,0,0,0,0,0,0,0,0,1,1,2 -Total,,,1,1,1,1,1,1,1,1,1,1,1,1,12 +,3.000,Count,0,0,0,0,0,0,1,0,0,0,0,0,1 +,4.000,Count,0,0,0,0,1,1,0,0,0,0,0,0,2 +,5.000,Count,0,0,1,0,0,0,0,0,0,0,0,0,1 +,6.000,Count,1,1,0,0,0,0,0,0,0,0,0,0,2 +,7.000,Count,0,0,0,0,0,0,0,1,0,0,0,0,1 +,8.000,Count,0,0,0,0,0,0,0,0,1,0,0,0,1 +,9.000,Count,0,0,0,0,0,0,0,0,0,1,0,0,1 +,10.000,Count,0,0,0,0,0,0,0,0,0,0,1,1,2 +Total,,Count,1,1,1,1,1,1,1,1,1,1,1,1,12 Table: Symmetric Measures ,,Value,Asymp. Std. Error,Approx. T @@ -1115,16 +1115,16 @@ Table: x × y ,,,y,,,,,,,,,,Total ,,,15000.00,26000.00,29000.00,32000.00,33000.00,41000.00,45000.00,52000.00,68000.00,80000.00, x,18.000,Count,1,0,0,0,0,0,0,0,0,0,1 -,24.000,,0,1,0,0,0,0,0,0,0,0,1 -,25.000,,0,0,1,0,0,0,0,0,0,0,1 -,26.000,,0,0,0,1,0,0,0,0,0,0,1 -,33.000,,0,0,0,0,1,0,0,0,0,0,1 -,37.000,,0,0,0,0,0,1,0,0,0,0,1 -,40.000,,0,0,0,0,0,0,1,0,0,0,1 -,45.000,,0,0,0,0,0,0,0,1,0,0,1 -,57.000,,0,0,0,0,0,0,0,0,1,0,1 -,64.000,,0,0,0,0,0,0,0,0,0,1,1 -Total,,,1,1,1,1,1,1,1,1,1,1,10 +,24.000,Count,0,1,0,0,0,0,0,0,0,0,1 +,25.000,Count,0,0,1,0,0,0,0,0,0,0,1 +,26.000,Count,0,0,0,1,0,0,0,0,0,0,1 +,33.000,Count,0,0,0,0,1,0,0,0,0,0,1 +,37.000,Count,0,0,0,0,0,1,0,0,0,0,1 +,40.000,Count,0,0,0,0,0,0,1,0,0,0,1 +,45.000,Count,0,0,0,0,0,0,0,1,0,0,1 +,57.000,Count,0,0,0,0,0,0,0,0,1,0,1 +,64.000,Count,0,0,0,0,0,0,0,0,0,1,1 +Total,,Count,1,1,1,1,1,1,1,1,1,1,10 Table: Symmetric Measures ,,Value,Asymp. Std. Error,Approx. T @@ -1675,8 +1675,8 @@ Table: p1 × p2 ,,,p2,,Total ,,,.000,1.000, p1,.000,Count,18.000,1.000,19.000 -,1.000,,1.000,.000,1.000 -Total,,,19.000,1.000,20.000 +,1.000,Count,1.000,.000,1.000 +Total,,Count,19.000,1.000,20.000 Table: Symmetric Measures ,,Value,Asymp. Std. Error,Approx. T @@ -1818,8 +1818,8 @@ Table: factor × disease ,,,disease,,Total ,,,Yes,No, factor,Placebo,Count,20,80,100 -,Aspirin,,15,135,150 -Total,,,35,215,250 +,Aspirin,Count,15,135,150 +Total,,Count,35,215,250 Table: Chi-Square Tests ,Value,df,Asymptotic Sig. (2-tailed),Exact Sig. (2-tailed),Exact Sig. (1-tailed) diff --git a/tests/language/stats/oneway.at b/tests/language/stats/oneway.at index 2c11e7ca46..9eb1a0811b 100644 --- a/tests/language/stats/oneway.at +++ b/tests/language/stats/oneway.at @@ -711,7 +711,7 @@ Tukey HSD,Placebo,1 Dose,-1.000,.887,.516,-3.366,1.366 ,,2 Doses,-1.800,.887,.147,-4.166,.566 ,2 Doses,Placebo,2.800,.887,.021,.434,5.166 ,,1 Dose,1.800,.887,.147,-.566,4.166 -Games-Howell,Placebo,,-1.000,.887,.479,-3.356,1.356 +Games-Howell,Placebo,1 Dose,-1.000,.887,.479,-3.356,1.356 ,,2 Doses,-2.800,.887,.039,-5.439,-.161 ,1 Dose,Placebo,1.000,.887,.479,-1.356,3.356 ,,2 Doses,-1.800,.887,.185,-4.439,.839