X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Flanguage%2Fstats%2Fexamine.c;h=46b27f9d360ac34b1161a69de910aadb18eaba43;hb=f481fd69631024bcdc7dc2369bbc1592d7a43ac7;hp=5d9f642641e038ec6dd343659bf6dbca52db1ba6;hpb=bb75ec3b2fe601c6b942f5cda283b82925dd745d;p=pspp diff --git a/src/language/stats/examine.c b/src/language/stats/examine.c index 5d9f642641..46b27f9d36 100644 --- a/src/language/stats/examine.c +++ b/src/language/stats/examine.c @@ -52,6 +52,7 @@ #include "output/charts/boxplot.h" #include "output/charts/np-plot.h" +#include "output/charts/spreadlevel-plot.h" #include "output/charts/plot-hist.h" #include "language/command.h" @@ -65,6 +66,14 @@ #define _(msgid) gettext (msgid) #define N_(msgid) msgid +static void +append_value_name (const struct variable *var, const union value *val, struct string *str) +{ + var_append_value_name (var, val, str); + if ( var_is_value_missing (var, val, MV_ANY)) + ds_put_cstr (str, _(" (missing)")); +} + enum bp_mode { BP_GROUPS, @@ -95,7 +104,8 @@ struct examine size_t n_iacts; struct interaction **iacts; - enum mv_class exclude; + enum mv_class dep_excl; + enum mv_class fctr_excl; const struct dictionary *dict; @@ -110,11 +120,9 @@ struct examine bool missing_pw; - /* Test options require that casenumbers are known */ - bool casenumbers; - /* The case index of the ID value (or -1) if not applicable */ size_t id_idx; + int id_width; enum pc_alg pc_alg; double *ptiles; @@ -123,6 +131,8 @@ struct examine bool npplot; bool histogram; bool boxplot; + bool spreadlevel; + int sl_power; enum bp_mode boxplot_mode; @@ -138,7 +148,7 @@ struct extremity /* Either the casenumber or the value of the variable specified by the /ID subcommand which corresponds to this extremity */ - double identity; + union value identity; }; struct exploratory_stats @@ -299,7 +309,7 @@ show_boxplot_grouped (const struct examine *cmd, int iact_idx) ds_put_cstr (&label, var_to_string (ivar)); ds_put_cstr (&label, " = "); - var_append_value_name (ivar, val, &label); + append_value_name (ivar, val, &label); ds_put_cstr (&label, "; "); } @@ -358,7 +368,7 @@ show_boxplot_variabled (const struct examine *cmd, int iact_idx) ds_put_cstr (&label, var_to_string (ivar)); ds_put_cstr (&label, " = "); - var_append_value_name (ivar, val, &label); + append_value_name (ivar, val, &label); ds_put_cstr (&label, "; "); } @@ -425,7 +435,7 @@ show_npplot (const struct examine *cmd, int iact_idx) ds_put_cstr (&label, var_to_string (ivar)); ds_put_cstr (&label, " = "); - var_append_value_name (ivar, val, &label); + append_value_name (ivar, val, &label); ds_put_cstr (&label, "; "); } @@ -457,6 +467,58 @@ show_npplot (const struct examine *cmd, int iact_idx) } } +static void +show_spreadlevel (const struct examine *cmd, int iact_idx) +{ + const struct interaction *iact = cmd->iacts[iact_idx]; + const size_t n_cats = categoricals_n_count (cmd->cats, iact_idx); + + int v; + + /* Spreadlevel when there are no levels is not useful */ + if (iact->n_vars == 0) + return; + + for (v = 0; v < cmd->n_dep_vars; ++v) + { + int grp; + struct chart_item *sl; + + struct string label; + ds_init_cstr (&label, + var_to_string (cmd->dep_vars[v])); + + if (iact->n_vars > 0) + { + ds_put_cstr (&label, " ("); + interaction_to_string (iact, &label); + ds_put_cstr (&label, ")"); + } + + sl = spreadlevel_plot_create (ds_cstr (&label), cmd->sl_power); + + for (grp = 0; grp < n_cats; ++grp) + { + const struct exploratory_stats *es = + categoricals_get_user_data_by_category_real (cmd->cats, iact_idx, grp); + + double median = percentile_calculate (es[v].quartiles[1], cmd->pc_alg); + + double iqr = percentile_calculate (es[v].quartiles[2], cmd->pc_alg) - + percentile_calculate (es[v].quartiles[0], cmd->pc_alg); + + spreadlevel_plot_add (sl, iqr, median); + } + + if (sl == NULL) + msg (MW, _("Not creating spreadlevel chart for %s"), ds_cstr (&label)); + else + chart_item_submit (sl); + + ds_destroy (&label); + } +} + static void show_histogram (const struct examine *cmd, int iact_idx) @@ -481,6 +543,10 @@ show_histogram (const struct examine *cmd, int iact_idx) categoricals_get_user_data_by_category_real (cmd->cats, iact_idx, grp); struct string label; + + if (es[v].histogram == NULL) + continue; + ds_init_cstr (&label, var_to_string (cmd->dep_vars[v])); @@ -494,7 +560,7 @@ show_histogram (const struct examine *cmd, int iact_idx) ds_put_cstr (&label, var_to_string (ivar)); ds_put_cstr (&label, " = "); - var_append_value_name (ivar, val, &label); + append_value_name (ivar, val, &label); ds_put_cstr (&label, "; "); } @@ -619,7 +685,7 @@ percentiles_report (const struct examine *cmd, int iact_idx) { struct string str; ds_init_empty (&str); - var_append_value_name (ivar, val, &str); + append_value_name (ivar, val, &str); tab_text (t, 1 + ivar_idx, @@ -787,7 +853,7 @@ descriptives_report (const struct examine *cmd, int iact_idx) { struct string str; ds_init_empty (&str); - var_append_value_name (ivar, val, &str); + append_value_name (ivar, val, &str); tab_text (t, 1 + ivar_idx, @@ -1103,7 +1169,7 @@ extremes_report (const struct examine *cmd, int iact_idx) { struct string str; ds_init_empty (&str); - var_append_value_name (ivar, val, &str); + append_value_name (ivar, val, &str); tab_text (t, 1 + ivar_idx, @@ -1150,22 +1216,29 @@ extremes_report (const struct examine *cmd, int iact_idx) &F_8_0); /* The casenumber */ - tab_double (t, + if (cmd->id_var) + tab_value (t, + heading_columns, + heading_rows + v * rows_per_var + i * rows_per_cat + e, + TAB_RIGHT, + &es->maxima[e].identity, + cmd->id_var, + NULL); + else + tab_double (t, heading_columns, - heading_rows + v * rows_per_var + i * rows_per_cat + e, - 0, - es->maxima[e].identity, - &F_8_0); - + heading_rows + v * rows_per_var + i * rows_per_cat + e, + TAB_RIGHT, + es->maxima[e].identity.f, + &F_8_0); tab_double (t, - heading_columns + 1, - heading_rows + v * rows_per_var + i * rows_per_cat + e, - 0, - es->maxima[e].val, - 0); - - + heading_columns + 1, + heading_rows + v * rows_per_var + i * rows_per_cat + e, + 0, + es->maxima[e].val, + var_get_print_format (cmd->dep_vars[v])); + tab_double (t, heading_columns - 1, @@ -1175,19 +1248,28 @@ extremes_report (const struct examine *cmd, int iact_idx) &F_8_0); /* The casenumber */ - tab_double (t, - heading_columns, - heading_rows + v * rows_per_var + i * rows_per_cat + cmd->disp_extremes + e, - 0, - es->minima[e].identity, - &F_8_0); + if (cmd->id_var) + tab_value (t, + heading_columns, + heading_rows + v * rows_per_var + i * rows_per_cat + cmd->disp_extremes + e, + TAB_RIGHT, + &es->minima[e].identity, + cmd->id_var, + NULL); + else + tab_double (t, + heading_columns, + heading_rows + v * rows_per_var + i * rows_per_cat + cmd->disp_extremes + e, + TAB_RIGHT, + es->minima[e].identity.f, + &F_8_0); tab_double (t, heading_columns + 1, heading_rows + v * rows_per_var + i * rows_per_cat + cmd->disp_extremes + e, 0, es->minima[e].val, - 0); + var_get_print_format (cmd->dep_vars[v])); } } free (prev_val); @@ -1305,7 +1387,7 @@ summary_report (const struct examine *cmd, int iact_idx) { struct string str; ds_init_empty (&str); - var_append_value_name (ivar, val, &str); + append_value_name (ivar, val, &str); tab_text (t, 1 + ivar_idx, heading_rows + n_cats * v + i, @@ -1465,7 +1547,7 @@ update_n (const void *aux1, void *aux2 UNUSED, void *user_data, const struct variable *var = examine->dep_vars[v]; const double x = case_data (c, var)->f; - if (var_is_value_missing (var, case_data (c, var), examine->exclude)) + if (var_is_value_missing (var, case_data (c, var), examine->dep_excl)) { es[v].missing += weight; continue; @@ -1483,10 +1565,11 @@ update_n (const void *aux1, void *aux2 UNUSED, void *user_data, moments_pass_one (es[v].mom, x, weight); - /* Save the value and the casenumber to the writer */ + /* Save the value and the ID to the writer */ + assert (examine->id_idx != -1); case_data_rw_idx (outcase, EX_VAL)->f = x; - if ( examine->id_idx != -1) - case_data_rw_idx (outcase, EX_ID)->f = case_data_idx (c, examine->id_idx)->f; + value_copy (case_data_rw_idx (outcase, EX_ID), + case_data_idx (c, examine->id_idx), examine->id_width); case_data_rw_idx (outcase, EX_WT)->f = weight; @@ -1518,12 +1601,10 @@ calculate_n (const void *aux1, void *aux2 UNUSED, void *user_data) if (examine->histogram) { /* Sturges Rule */ - double bin_width = abs (es[v].minimum - es[v].maximum) + double bin_width = fabs (es[v].minimum - es[v].maximum) / (1 + log2 (es[v].cc)) ; - bin_width = chart_rounded_tick (bin_width); - es[v].histogram = histogram_create (bin_width, es[v].minimum, es[v].maximum); } @@ -1534,6 +1615,11 @@ calculate_n (const void *aux1, void *aux2 UNUSED, void *user_data) es[v].maxima = pool_calloc (examine->pool, examine->calc_extremes, sizeof (*es[v].maxima)); es[v].minima = pool_calloc (examine->pool, examine->calc_extremes, sizeof (*es[v].minima)); + for (i = 0; i < examine->calc_extremes; ++i) + { + value_init_pool (examine->pool, &es[v].maxima[i].identity, examine->id_width) ; + value_init_pool (examine->pool, &es[v].minima[i].identity, examine->id_width) ; + } for (reader = casereader_clone (es[v].sorted_reader); (c = casereader_read (reader)) != NULL; case_unref (c)) @@ -1553,7 +1639,7 @@ calculate_n (const void *aux1, void *aux2 UNUSED, void *user_data) { struct extremity *min = &es[v].minima[x]; min->val = val; - min->identity = case_data_idx (c, EX_ID)->f; + value_copy (&min->identity, case_data_idx (c, EX_ID), examine->id_width); } imin += wt; } @@ -1572,7 +1658,7 @@ calculate_n (const void *aux1, void *aux2 UNUSED, void *user_data) max = &es[v].maxima[x]; max->val = val; - max->identity = case_data_idx (c, EX_ID)->f; + value_copy (&max->identity, case_data_idx (c, EX_ID), examine->id_width); } } } @@ -1623,7 +1709,7 @@ calculate_n (const void *aux1, void *aux2 UNUSED, void *user_data) struct order_stats *os; es[v].box_whisker = box_whisker_create (es[v].hinges, - EX_ID); + EX_ID, examine->id_var); os = &es[v].box_whisker->parent; order_stats_accumulate_idx (&os, 1, @@ -1717,40 +1803,35 @@ run_examine (struct examine *cmd, struct casereader *input) struct payload payload; payload.create = create_n; payload.update = update_n; - payload.destroy = calculate_n; + payload.calculate = calculate_n; + payload.destroy = NULL; cmd->wv = dict_get_weight (cmd->dict); - cmd->id_idx = -1; cmd->cats = categoricals_create (cmd->iacts, cmd->n_iacts, - cmd->wv, cmd->exclude); + cmd->wv, cmd->dep_excl, cmd->fctr_excl); categoricals_set_payload (cmd->cats, &payload, cmd, NULL); - if (cmd->casenumbers) + if (cmd->id_idx == -1) { struct ccase *c = casereader_peek (input, 0); - if (cmd->id_var) - cmd->id_idx = var_get_case_index (cmd->id_var); - else - { - cmd->id_idx = case_get_value_cnt (c); - input = casereader_create_arithmetic_sequence (input, 1.0, 1.0); - } + assert (cmd->id_var == NULL); + + cmd->id_idx = case_get_value_cnt (c); + input = casereader_create_arithmetic_sequence (input, 1.0, 1.0); case_unref (c); } - /* FIXME: Filter out missing factor variables */ - /* Remove cases on a listwise basis if requested */ if ( cmd->missing_pw == false) input = casereader_create_filter_missing (input, cmd->dep_vars, cmd->n_dep_vars, - cmd->exclude, + cmd->dep_excl, NULL, NULL); @@ -1794,6 +1875,9 @@ run_examine (struct examine *cmd, struct casereader *input) if (cmd->npplot) show_npplot (cmd, i); + if (cmd->spreadlevel) + show_spreadlevel (cmd, i); + if (cmd->descriptives) descriptives_report (cmd, i); } @@ -1814,7 +1898,6 @@ cmd_examine (struct lexer *lexer, struct dataset *ds) struct examine examine; bool percentiles_seen = false; - examine.casenumbers = false; examine.missing_pw = false; examine.disp_extremes = 0; examine.calc_extremes = 0; @@ -1823,13 +1906,12 @@ cmd_examine (struct lexer *lexer, struct dataset *ds) examine.pc_alg = PC_HAVERAGE; examine.ptiles = NULL; examine.n_percentiles = 0; - examine.id_var = 0; + examine.id_idx = -1; + examine.id_width = 0; + examine.id_var = NULL; examine.boxplot_mode = BP_GROUPS; examine.ex_proto = caseproto_create (); - examine.ex_proto = caseproto_add_width (examine.ex_proto, 0); /* value */ - examine.ex_proto = caseproto_add_width (examine.ex_proto, 0); /* id */ - examine.ex_proto = caseproto_add_width (examine.ex_proto, 0); /* weight */ examine.pool = pool_create (); @@ -1842,10 +1924,13 @@ cmd_examine (struct lexer *lexer, struct dataset *ds) examine.iacts = iacts_mem = pool_zalloc (examine.pool, sizeof (struct interaction *)); examine.iacts[0] = interaction_create (NULL); - examine.exclude = MV_ANY; + examine.dep_excl = MV_ANY; + examine.fctr_excl = MV_ANY; examine.histogram = false; examine.npplot = false; examine.boxplot = false; + examine.spreadlevel = false; + examine.sl_power = 0; examine.dict = dataset_dict (ds); @@ -2024,11 +2109,19 @@ cmd_examine (struct lexer *lexer, struct dataset *ds) } else if (lex_match_id (lexer, "EXCLUDE")) { - examine.exclude = MV_ANY; + examine.dep_excl = MV_ANY; } else if (lex_match_id (lexer, "INCLUDE")) { - examine.exclude = MV_SYSTEM; + examine.dep_excl = MV_SYSTEM; + } + else if (lex_match_id (lexer, "REPORT")) + { + examine.fctr_excl = MV_NEVER; + } + else if (lex_match_id (lexer, "NOREPORT")) + { + examine.fctr_excl = MV_ANY; } else { @@ -2073,6 +2166,19 @@ cmd_examine (struct lexer *lexer, struct dataset *ds) { examine.histogram = true; } + else if (lex_match_id (lexer, "SPREADLEVEL")) + { + examine.spreadlevel = true; + examine.sl_power = 0; + if (lex_match (lexer, T_LPAREN)) + { + examine.sl_power = lex_integer (lexer); + + lex_get (lexer); + if (! lex_force_match (lexer, T_RPAREN)) + goto error; + } + } else if (lex_match_id (lexer, "NONE")) { examine.histogram = false; @@ -2114,6 +2220,7 @@ cmd_examine (struct lexer *lexer, struct dataset *ds) } } + if ( totals_seen && nototals_seen) { msg (SE, _("%s and %s are mutually exclusive"),"TOTAL","NOTOTAL"); @@ -2130,21 +2237,26 @@ cmd_examine (struct lexer *lexer, struct dataset *ds) { examine.n_iacts--; examine.iacts = &iacts_mem[1]; + interaction_destroy (iacts_mem[0]); } - if (examine.disp_extremes > 0) + if ( examine.id_var ) { - examine.calc_extremes = examine.disp_extremes; - examine.casenumbers = true; + examine.id_idx = var_get_case_index (examine.id_var); + examine.id_width = var_get_width (examine.id_var); } - if (examine.boxplot) + examine.ex_proto = caseproto_add_width (examine.ex_proto, 0); /* value */ + examine.ex_proto = caseproto_add_width (examine.ex_proto, examine.id_width); /* id */ + examine.ex_proto = caseproto_add_width (examine.ex_proto, 0); /* weight */ + + + if (examine.disp_extremes > 0) { - examine.casenumbers = true; + examine.calc_extremes = examine.disp_extremes; } - if (examine.descriptives && examine.calc_extremes == 0) { /* Descriptives always displays the max and min */ @@ -2181,9 +2293,6 @@ cmd_examine (struct lexer *lexer, struct dataset *ds) caseproto_unref (examine.ex_proto); - for (i = 0; i < examine.n_iacts; ++i) - interaction_destroy (examine.iacts[i]); - free (examine.ptiles); free (examine.dep_vars); pool_destroy (examine.pool); @@ -2192,6 +2301,7 @@ cmd_examine (struct lexer *lexer, struct dataset *ds) error: caseproto_unref (examine.ex_proto); + examine.iacts = iacts_mem; for (i = 0; i < examine.n_iacts; ++i) interaction_destroy (examine.iacts[i]); free (examine.dep_vars);