-/* This file is part of GNU PSPP
- Computes Levene test statistic.
+/* PSPP - a program for statistical analysis.
+ Copyright (C) 2004, 2009 Free Software Foundation, Inc.
- Copyright (C) 2004 Free Software Foundation, Inc.
+ 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 3 of the License, or
+ (at your option) any later version.
- 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.
+ 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., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA. */
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include "levene.h"
#include <libpspp/message.h>
#include <data/case.h>
-#include <data/casefile.h>
+#include <data/casereader.h>
#include <data/dictionary.h>
#include "group-proc.h"
#include <libpspp/hash.h>
#include <libpspp/str.h>
#include <data/variable.h>
#include <data/procedure.h>
-#include <data/casefilter.h>
-#include <libpspp/alloc.h>
#include <libpspp/misc.h>
#include "group.h"
#include <math.h>
#include <stdlib.h>
+#include "xalloc.h"
+
/* This module calculates the Levene statistic for variables.
struct t_test_proc **group_stats;
/* The independent variable */
- const struct variable *v_indep;
+ const struct variable *v_indep;
/* Number of dependent variables */
size_t n_dep;
const struct variable **v_dep;
/* Filter for missing values */
- struct casefilter *filter;
+ enum mv_class exclude;
+
+ /* An array of lz_stats for each variable */
+ struct lz_stats *lz;
+
+ /* The denominator for the expression for the Levene */
+ double *lz_denominator;
+
+};
+
+/* Per variable statistics */
+struct lz_stats
+{
+ /* Total of all lz */
+ double grand_total;
+
+ /* Mean of all lz */
+ double grand_mean;
+
+ /* The total number of cases */
+ double total_n ;
+
+ /* Number of groups */
+ int n_groups;
};
/* First pass */
static void levene_precalc (const struct levene_info *l);
-static int levene_calc (const struct dictionary *dict, const struct ccase *,
+static int levene_calc (const struct dictionary *dict, const struct ccase *,
const struct levene_info *l);
-static void levene_postcalc (void *);
+static void levene_postcalc (struct levene_info *);
/* Second pass */
static void levene2_precalc (struct levene_info *l);
-static int levene2_calc (const struct dictionary *, const struct ccase *,
+static int levene2_calc (const struct dictionary *, const struct ccase *,
struct levene_info *l);
-static void levene2_postcalc (void *);
+static void levene2_postcalc (struct levene_info *);
-void
-levene(const struct dictionary *dict,
- const struct casefile *cf,
- const struct variable *v_indep, size_t n_dep,
+void
+levene(const struct dictionary *dict,
+ struct casereader *reader,
+ const struct variable *v_indep, size_t n_dep,
const struct variable **v_dep,
- struct casefilter *filter)
+ enum mv_class exclude)
{
- struct casereader *r;
- struct ccase c;
+ struct casereader *pass1, *pass2;
+ struct ccase *c;
struct levene_info l;
l.n_dep = n_dep;
l.v_indep = v_indep;
l.v_dep = v_dep;
- l.filter = filter;
+ l.exclude = exclude;
+ l.lz = xnmalloc (l.n_dep, sizeof *l.lz);
+ l.lz_denominator = xnmalloc (l.n_dep, sizeof *l.lz_denominator);
+ casereader_split (reader, &pass1, &pass2);
levene_precalc (&l);
- for(r = casefile_get_reader (cf, filter);
- casereader_read (r, &c) ;
- case_destroy (&c))
- {
- levene_calc (dict, &c, &l);
- }
- casereader_destroy (r);
+ for (; (c = casereader_read (pass1)) != NULL; case_unref (c))
+ levene_calc (dict, c, &l);
+ casereader_destroy (pass1);
levene_postcalc (&l);
levene2_precalc(&l);
- for(r = casefile_get_reader (cf, filter);
- casereader_read (r, &c) ;
- case_destroy (&c))
- {
- levene2_calc (dict, &c,&l);
- }
- casereader_destroy (r);
+ for (; (c = casereader_read (pass2)) != NULL; case_unref (c))
+ levene2_calc (dict, c, &l);
+ casereader_destroy (pass2);
levene2_postcalc (&l);
-}
-
-/* Internal variables used in calculating the Levene statistic */
-
-/* Per variable statistics */
-struct lz_stats
-{
- /* Total of all lz */
- double grand_total;
-
- /* Mean of all lz */
- double grand_mean;
-
- /* The total number of cases */
- double total_n ;
-
- /* Number of groups */
- int n_groups;
-};
-
-/* An array of lz_stats for each variable */
-static struct lz_stats *lz;
+ free (l.lz_denominator);
+ free (l.lz);
+}
-static void
+static void
levene_precalc (const struct levene_info *l)
{
size_t i;
- lz = xnmalloc (l->n_dep, sizeof *lz);
-
- for(i = 0; i < l->n_dep ; ++i )
+ for(i = 0; i < l->n_dep ; ++i )
{
const struct variable *var = l->v_dep[i];
struct group_proc *gp = group_proc_get (var);
struct group_statistics *gs;
struct hsh_iterator hi;
- lz[i].grand_total = 0;
- lz[i].total_n = 0;
- lz[i].n_groups = gp->n_groups ;
+ l->lz[i].grand_total = 0;
+ l->lz[i].total_n = 0;
+ l->lz[i].n_groups = gp->n_groups ;
+
-
for ( gs = hsh_first(gp->group_hash, &hi);
gs != 0;
gs = hsh_next(gp->group_hash, &hi))
{
gs->lz_total = 0;
}
-
+
}
}
-static int
-levene_calc (const struct dictionary *dict, const struct ccase *c,
+static int
+levene_calc (const struct dictionary *dict, const struct ccase *c,
const struct levene_info *l)
{
size_t i;
bool warn = false;
const union value *gv = case_data (c, l->v_indep);
struct group_statistics key;
- double weight = dict_get_case_weight (dict, c, &warn);
+ double weight = dict_get_case_weight (dict, c, &warn);
key.id = *gv;
- for (i = 0; i < l->n_dep; ++i)
+ for (i = 0; i < l->n_dep; ++i)
{
const struct variable *var = l->v_dep[i];
struct group_proc *gp = group_proc_get (var);
gs = hsh_find(gp->group_hash,(void *) &key );
- if ( 0 == gs )
+ if ( 0 == gs )
continue ;
- if ( ! casefilter_variable_missing (l->filter, c, var))
+ if ( !var_is_value_missing (var, v, l->exclude))
{
levene_z= fabs(v->f - gs->mean);
- lz[i].grand_total += levene_z * weight;
- lz[i].total_n += weight;
+ l->lz[i].grand_total += levene_z * weight;
+ l->lz[i].total_n += weight;
gs->lz_total += levene_z * weight;
}
}
-static void
-levene_postcalc (void *_l)
+static void
+levene_postcalc (struct levene_info *l)
{
size_t v;
- struct levene_info *l = (struct levene_info *) _l;
-
- for (v = 0; v < l->n_dep; ++v)
+ for (v = 0; v < l->n_dep; ++v)
{
/* This is Z_LL */
- lz[v].grand_mean = lz[v].grand_total / lz[v].total_n ;
+ l->lz[v].grand_mean = l->lz[v].grand_total / l->lz[v].total_n ;
}
-
-}
+}
-/* The denominator for the expression for the Levene */
-static double *lz_denominator = 0;
-static void
+static void
levene2_precalc (struct levene_info *l)
{
size_t v;
- lz_denominator = xnmalloc (l->n_dep, sizeof *lz_denominator);
/* This stuff could go in the first post calc . . . */
- for (v = 0;
- v < l->n_dep;
- ++v)
+ for (v = 0;
+ v < l->n_dep;
+ ++v)
{
struct hsh_iterator hi;
struct group_statistics *g;
{
g->lz_mean = g->lz_total / g->n ;
}
- lz_denominator[v] = 0;
+ l->lz_denominator[v] = 0;
}
}
-static int
-levene2_calc (const struct dictionary *dict, const struct ccase *c,
+static int
+levene2_calc (const struct dictionary *dict, const struct ccase *c,
struct levene_info *l)
{
size_t i;
bool warn = false;
- double weight = dict_get_case_weight (dict, c, &warn);
+ double weight = dict_get_case_weight (dict, c, &warn);
const union value *gv = case_data (c, l->v_indep);
struct group_statistics key;
key.id = *gv;
- for (i = 0; i < l->n_dep; ++i)
+ for (i = 0; i < l->n_dep; ++i)
{
double levene_z;
const struct variable *var = l->v_dep[i] ;
gs = hsh_find(group_proc_get (var)->group_hash,(void *) &key );
- if ( 0 == gs )
+ if ( 0 == gs )
continue;
- if ( ! casefilter_variable_missing (l->filter, c, var))
-
+ if ( !var_is_value_missing (var, v, l->exclude))
{
- levene_z = fabs(v->f - gs->mean);
- lz_denominator[i] += weight * pow2 (levene_z - gs->lz_mean);
+ levene_z = fabs(v->f - gs->mean);
+ l->lz_denominator[i] += weight * pow2 (levene_z - gs->lz_mean);
}
}
}
-static void
-levene2_postcalc (void *_l)
+static void
+levene2_postcalc (struct levene_info *l)
{
size_t v;
- struct levene_info *l = (struct levene_info *) _l;
-
- for (v = 0; v < l->n_dep; ++v)
+ for (v = 0; v < l->n_dep; ++v)
{
double lz_numerator = 0;
struct hsh_iterator hi;
g != 0 ;
g = (struct group_statistics *) hsh_next(hash,&hi) )
{
- lz_numerator += g->n * pow2(g->lz_mean - lz[v].grand_mean );
+ lz_numerator += g->n * pow2(g->lz_mean - l->lz[v].grand_mean );
}
lz_numerator *= ( gp->ugs.n - gp->n_groups );
- lz_denominator[v] *= (gp->n_groups - 1);
+ l->lz_denominator[v] *= (gp->n_groups - 1);
- gp->levene = lz_numerator / lz_denominator[v] ;
+ gp->levene = lz_numerator / l->lz_denominator[v] ;
}
-
- /* Now clear up after ourselves */
- free(lz_denominator);
- free(lz);
}