/* PSPP - One way ANOVA. -*-c-*- Copyright (C) 1997-9, 2000 Free Software Foundation, Inc. Author: John Darrington 2004 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include "error.h" #include #include #include #include "alloc.h" #include "str.h" #include "case.h" #include "command.h" #include "lexer.h" #include "error.h" #include "magic.h" #include "misc.h" #include "tab.h" #include "som.h" #include "value-labels.h" #include "var.h" #include "vfm.h" #include "hash.h" #include "casefile.h" #include "levene.h" /* (specification) "ONEWAY" (oneway_): *variables=custom; +missing=miss:!analysis/listwise, incl:include/!exclude; contrast= double list; statistics[st_]=descriptives,homogeneity. */ /* (declarations) */ /* (functions) */ static struct cmd_oneway cmd; /* The independent variable */ static struct variable *indep_var; /* A hash of the values of the independent variable */ struct hsh_table *ind_vals; /* Number of factors (groups) */ static int n_groups; /* Number of dependent variables */ static int n_vars; /* The dependent variables */ static struct variable **vars; /* Function to use for testing for missing values */ static is_missing_func value_is_missing; static void calculate(const struct casefile *cf, void *_mode); /* Routines to show the output tables */ static void show_anova_table(void); static void show_descriptives(void); static void show_homogeneity(void); static void show_contrast_coeffs(void); static void show_contrast_tests(void); int cmd_oneway(void) { int i; if ( !parse_oneway(&cmd) ) return CMD_FAILURE; /* If /MISSING=INCLUDE is set, then user missing values are ignored */ if (cmd.incl == ONEWAY_INCLUDE ) value_is_missing = is_system_missing; else value_is_missing = is_missing; multipass_procedure_with_splits (calculate, &cmd); /* Check the sanity of the given contrast values */ for (i = 0 ; i < cmd.sbc_contrast ; ++i ) { int j; double sum = 0; if ( subc_list_double_count(&cmd.dl_contrast[i]) != n_groups ) { msg(SE, _("Number of contrast coefficients must equal the number of groups")); return CMD_FAILURE; } for (j=0; j < n_groups ; ++j ) sum += subc_list_double_at(&cmd.dl_contrast[i],j); if ( sum != 0.0 ) msg(SW,_("Coefficients for contrast %d do not total zero"),i + 1); } /* Show the statistics tables */ if ( cmd.sbc_statistics ) { for (i = 0 ; i < ONEWAY_ST_count ; ++i ) { if ( ! cmd.a_statistics[i] ) continue; switch (i) { case ONEWAY_ST_DESCRIPTIVES: show_descriptives(); break; case ONEWAY_ST_HOMOGENEITY: show_homogeneity(); break; } } } show_anova_table(); if (cmd.sbc_contrast) { show_contrast_coeffs(); show_contrast_tests(); } hsh_destroy(ind_vals); return CMD_SUCCESS; } /* Parser for the variables sub command */ static int oneway_custom_variables(struct cmd_oneway *cmd UNUSED) { lex_match('='); if ((token != T_ID || dict_lookup_var (default_dict, tokid) == NULL) && token != T_ALL) return 2; if (!parse_variables (default_dict, &vars, &n_vars, PV_DUPLICATE | PV_NUMERIC | PV_NO_SCRATCH) ) { free (vars); return 0; } assert(n_vars); if ( ! lex_match(T_BY)) return 2; indep_var = parse_variable(); if ( !indep_var ) { msg(SE,_("`%s' is not a variable name"),tokid); return 0; } return 1; } /* Show the ANOVA table */ static void show_anova_table(void) { int i; int n_cols =7; int n_rows = n_vars * 3 + 1; struct tab_table *t; t = tab_create (n_cols,n_rows,0); tab_headers (t, 2, 0, 1, 0); tab_dim (t, tab_natural_dimensions); tab_box (t, TAL_2, TAL_2, -1, TAL_1, 0, 0, n_cols - 1, n_rows - 1); tab_hline (t, TAL_2, 0, n_cols - 1, 1 ); tab_vline (t, TAL_2, 2, 0, n_rows - 1); tab_vline (t, TAL_0, 1, 0, 0); tab_text (t, 2, 0, TAB_CENTER | TAT_TITLE, _("Sum of Squares")); tab_text (t, 3, 0, TAB_CENTER | TAT_TITLE, _("df")); tab_text (t, 4, 0, TAB_CENTER | TAT_TITLE, _("Mean Square")); tab_text (t, 5, 0, TAB_CENTER | TAT_TITLE, _("F")); tab_text (t, 6, 0, TAB_CENTER | TAT_TITLE, _("Significance")); for ( i=0 ; i < n_vars ; ++i ) { char *s = (vars[i]->label) ? vars[i]->label : vars[i]->name; tab_text (t, 0, i * 3 + 1, TAB_LEFT | TAT_TITLE, s); tab_text (t, 1, i * 3 + 1, TAB_LEFT | TAT_TITLE, _("Between Groups")); tab_text (t, 1, i * 3 + 2, TAB_LEFT | TAT_TITLE, _("Within Groups")); tab_text (t, 1, i * 3 + 3, TAB_LEFT | TAT_TITLE, _("Total")); if (i > 0) tab_hline(t, TAL_1, 0, n_cols - 1 , i * 3 + 1); } tab_title (t, 0, "ANOVA"); tab_submit (t); } static void calculate(const struct casefile *cf, void *cmd_) { struct casereader *r; struct ccase c; struct cmd_t_test *cmd = (struct cmd_t_test *) cmd_; ind_vals = hsh_create(4, (hsh_compare_func *) compare_values, (hsh_hash_func *) hash_value, 0, (void *) indep_var->width ); for(r = casefile_get_reader (cf); casereader_read (r, &c) ; case_destroy (&c)) { const union value *val = case_data (&c, indep_var->fv); hsh_insert(ind_vals, (void *) val); /* if (! value_is_missing(val,v) ) { gs->n+=weight; gs->sum+=weight * val->f; gs->ssq+=weight * val->f * val->f; } */ } casereader_destroy (r); n_groups = hsh_count(ind_vals); } /* Show the descriptives table */ static void show_descriptives(void) { int v; int n_cols =10; int n_rows = n_vars * (n_groups + 1 )+ 2; struct tab_table *t; t = tab_create (n_cols,n_rows,0); tab_headers (t, 2, 0, 2, 0); tab_dim (t, tab_natural_dimensions); /* Put a frame around the entire box, and vertical lines inside */ tab_box (t, TAL_2, TAL_2, -1, TAL_1, 0, 0, n_cols - 1, n_rows - 1); /* Underline headers */ tab_hline (t, TAL_2, 0, n_cols - 1, 2 ); tab_vline (t, TAL_2, 2, 0, n_rows - 1); tab_text (t, 2, 1, TAB_CENTER | TAT_TITLE, _("N")); tab_text (t, 3, 1, TAB_CENTER | TAT_TITLE, _("Mean")); tab_text (t, 4, 1, TAB_CENTER | TAT_TITLE, _("Std. Deviation")); tab_text (t, 5, 1, TAB_CENTER | TAT_TITLE, _("Std. Error")); tab_vline(t, TAL_0, 7, 0, 0); tab_hline(t, TAL_1, 6, 7, 1); tab_joint_text (t, 6, 0, 7, 0, TAB_CENTER | TAT_TITLE, _("95% Confidence Interval for Mean")); tab_text (t, 6, 1, TAB_CENTER | TAT_TITLE, _("Lower Bound")); tab_text (t, 7, 1, TAB_CENTER | TAT_TITLE, _("Upper Bound")); tab_text (t, 8, 1, TAB_CENTER | TAT_TITLE, _("Minimum")); tab_text (t, 9, 1, TAB_CENTER | TAT_TITLE, _("Maximum")); tab_title (t, 0, "Descriptives"); for ( v=0 ; v < n_vars ; ++v ) { struct hsh_iterator g; union value *group_value; int count = 0 ; char *s = (vars[v]->label) ? vars[v]->label : vars[v]->name; tab_text (t, 0, v * ( n_groups + 1 ) + 2, TAB_LEFT | TAT_TITLE, s); if ( v > 0) tab_hline(t, TAL_1, 0, n_cols - 1 , v * (n_groups + 1) + 2); for (group_value = hsh_first (ind_vals,&g); group_value != 0; group_value = hsh_next(ind_vals,&g)) { char *lab; lab = val_labs_find(indep_var->val_labs,*group_value); if ( lab ) tab_text (t, 1, v * (n_groups + 1)+ count + 2, TAB_LEFT | TAT_TITLE ,lab); else tab_text (t, 1, v * (n_groups + 1) + count + 2, TAB_LEFT | TAT_TITLE | TAT_PRINTF, "%g", group_value->f); count++ ; } tab_text (t, 1, v * (n_groups + 1)+ count + 2, TAB_LEFT | TAT_TITLE ,_("Total")); } tab_submit (t); } /* Show the homogeneity table */ static void show_homogeneity(void) { int v; int n_cols = 5; int n_rows = n_vars + 1; struct tab_table *t; t = tab_create (n_cols,n_rows,0); tab_headers (t, 1, 0, 1, 0); tab_dim (t, tab_natural_dimensions); /* Put a frame around the entire box, and vertical lines inside */ tab_box (t, TAL_2, TAL_2, -1, TAL_1, 0, 0, n_cols - 1, n_rows - 1); tab_hline(t, TAL_2, 0, n_cols - 1, 1); tab_vline(t, TAL_2, 1, 0, n_rows - 1); tab_text (t, 1, 0, TAB_CENTER | TAT_TITLE, _("Levene Statistic")); tab_text (t, 2, 0, TAB_CENTER | TAT_TITLE, _("df1")); tab_text (t, 3, 0, TAB_CENTER | TAT_TITLE, _("df2")); tab_text (t, 4, 0, TAB_CENTER | TAT_TITLE, _("Significance")); tab_title (t, 0, _("Test of Homogeneity of Variances")); for ( v=0 ; v < n_vars ; ++v ) { char *s = (vars[v]->label) ? vars[v]->label : vars[v]->name; tab_text (t, 0, v + 1, TAB_LEFT | TAT_TITLE, s); } tab_submit (t); } /* Show the contrast coefficients table */ static void show_contrast_coeffs(void) { char *s; int n_cols = 2 + n_groups; int n_rows = 2 + cmd.sbc_contrast; struct hsh_iterator g; union value *group_value; int count = 0 ; struct tab_table *t; t = tab_create (n_cols,n_rows,0); tab_headers (t, 2, 0, 2, 0); tab_dim (t, tab_natural_dimensions); /* Put a frame around the entire box, and vertical lines inside */ tab_box (t, TAL_2, TAL_2, -1, TAL_1, 0, 0, n_cols - 1, n_rows - 1); tab_box (t, -1,-1, TAL_0, TAL_0, 2, 0, n_cols - 1, 0); tab_box (t, -1,-1, TAL_0, TAL_0, 0,0, 1,1); tab_hline(t, TAL_1, 2, n_cols - 1, 1); tab_hline(t, TAL_2, 0, n_cols - 1, 2); tab_vline(t, TAL_2, 2, 0, n_rows - 1); tab_title (t, 0, _("Contrast Coefficients")); tab_text (t, 0, 2, TAB_LEFT | TAT_TITLE, _("Contrast")); s = (indep_var->label) ? indep_var->label : indep_var->name; tab_joint_text (t, 2, 0, n_cols - 1, 0, TAB_CENTER | TAT_TITLE, s); for (group_value = hsh_first (ind_vals,&g); group_value != 0; group_value = hsh_next(ind_vals,&g)) { int i; char *lab; lab = val_labs_find(indep_var->val_labs,*group_value); if ( lab ) tab_text (t, count + 2, 1, TAB_CENTER | TAT_TITLE ,lab); else tab_text (t, count + 2, 1, TAB_CENTER | TAT_TITLE | TAT_PRINTF, "%g", group_value->f); for (i = 0 ; i < cmd.sbc_contrast ; ++i ) { tab_text(t, 1, i + 2, TAB_CENTER | TAT_PRINTF, "%d", i + 1); tab_text(t, count + 2, i + 2, TAB_RIGHT | TAT_PRINTF, "%g", subc_list_double_at(&cmd.dl_contrast[i],count) ); } count++ ; } tab_submit (t); } /* Show the results of the contrast tests */ static void show_contrast_tests(void) { int v; int n_cols = 8; int n_rows = 1 + n_vars * 2 * cmd.sbc_contrast; struct tab_table *t; t = tab_create (n_cols,n_rows,0); tab_headers (t, 3, 0, 1, 0); tab_dim (t, tab_natural_dimensions); /* Put a frame around the entire box, and vertical lines inside */ tab_box (t, TAL_2, TAL_2, -1, TAL_1, 0, 0, n_cols - 1, n_rows - 1); tab_box (t, -1,-1, TAL_0, TAL_0, 0, 0, 2, 0); tab_hline(t, TAL_2, 0, n_cols - 1, 1); tab_vline(t, TAL_2, 3, 0, n_rows - 1); tab_title (t, 0, _("Contrast Tests")); tab_text (t, 2, 0, TAB_CENTER | TAT_TITLE, _("Contrast")); tab_text (t, 3, 0, TAB_CENTER | TAT_TITLE, _("Value of Contrast")); tab_text (t, 4, 0, TAB_CENTER | TAT_TITLE, _("Std. Error")); tab_text (t, 5, 0, TAB_CENTER | TAT_TITLE, _("t")); tab_text (t, 6, 0, TAB_CENTER | TAT_TITLE, _("df")); tab_text (t, 7, 0, TAB_CENTER | TAT_TITLE, _("Sig. (2-tailed)")); for ( v = 0 ; v < n_vars ; ++v ) { int i; int lines_per_variable = 2 * cmd.sbc_contrast; tab_text (t, 0, (v * lines_per_variable) + 1, TAB_LEFT | TAT_TITLE, vars[v]->label?vars[v]->label:vars[v]->name); for ( i = 0 ; i < cmd.sbc_contrast ; ++i ) { tab_text (t, 1, (v * lines_per_variable) + i*2 + 1, TAB_LEFT | TAT_TITLE, _("Assume equal variances")); tab_text (t, 1, (v * lines_per_variable) + i*2 + 2, TAB_LEFT | TAT_TITLE, _("Does not assume equal")); tab_text (t, 2, (v * lines_per_variable) + i*2 + 1, TAB_CENTER | TAT_TITLE | TAT_PRINTF, "%d",i+1); tab_text (t, 2, (v * lines_per_variable) + i*2 + 2, TAB_CENTER | TAT_TITLE | TAT_PRINTF, "%d",i+1); } if ( v > 0 ) tab_hline(t, TAL_1, 0, n_cols - 1, (v * lines_per_variable) + 1); } tab_submit (t); }