|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T o
Length: 5178 (0x143a)
Types: TextFile
Names: »oneway.c«
└─⟦87ddcff64⟧ Bits:30001253 CPHDIST85 Tape, 1985 Autumn Conference Copenhagen
└─⟦this⟧ »cph85dist/stat/src/oneway.c«
#include "unixstat.h"
PGM(oneway,one-way between groups t-test/anova,1.0,3/9/85)
main (argc, argv) char **argv;
{
ARGV0;
initial (argc, argv);
checkstdin (Argv0);
readdata ();
printstats ();
oneway ();
exit (0);
}
#define MAXGROUP 20
char *Name[MAXGROUP]; /* names of the different groups */
int Ngroups = 0; /* number of groups of data */
int Count[MAXGROUP]; /* number of cells in each group */
double Sum[MAXGROUP]; /* sum of all values in the group */
double Sumsq[MAXGROUP]; /* sums of squares */
double Min[MAXGROUP]; /* min value in the group */
double Max[MAXGROUP]; /* max value in the group */
/* OPTIONS */
double Splitter = -1.0; /* used to indicate group differences */
int Ttest = 0; /* Ttest format for two group case */
#define OPTSTRING "ts:"
initial (argc, argv) char **argv;
{
extern char *optarg;
extern int optind;
int errflg = 0;
int C;
int group;
while ((C = getopt (argc, argv, OPTSTRING)) != EOF)
switch (C)
{
case 's':
if (!number (optarg)) ERRNUM (optarg,group splitter)
Splitter = atof (optarg);
break;
case 't': Ttest = 1; break;
default: errflg++; break;
}
if (errflg)
USAGE ([-t] [-s splitter] [names])
for (group = 0; optind + group < argc; group++)
Name[group] = argv[optind+group];
}
readdata ()
{
char word[BUFSIZ]; /* string input data read in here */
double datum; /* each data value */
int grindex = 0; /* group index == Ngroups - 1 */
while (getword (word, stdin))
{
if (!number (word)) ERRNUM (word,input data)
datum = atof (word);
if (datum == Splitter) /* new group */
{
if (Count[grindex] != 0) /* until some data read for this group */
grindex = Ngroups++;
}
else /* real datum */
{
if (grindex >= MAXGROUP)
ERRMANY (groups,MAXGROUP)
if (Count[grindex] == 0)
{
if (Ngroups == 0) Ngroups = 1;
Min[grindex] = Max[grindex] = datum;
}
else
{
if (datum < Min[grindex]) Min[grindex] = datum;
else if (datum > Max[grindex]) Max[grindex] = datum;
}
Sum[grindex] += datum;
Sumsq[grindex] += datum * datum;
Count[grindex]++;
}
}
if (Count[grindex] == 0) Ngroups--; /* ignore empty last group */
if (Ngroups > MAXGROUP) ERRMANY (groups,MAXGROUP)
if (Ngroups == 0) ERRDATA
}
printstats ()
{
int group;
if (Ngroups)
printf ("%-9.9s %5s %8s %8s %8s %8s\n",
"Name", "N", "Mean", "SD", "Min", "Max");
for (group = 0; group < Ngroups; group++)
{
if (Name[group] && *Name[group])
printf ("%-9.9s ", Name[group]);
else printf ("Group-%-3d ", group+1);
printf ("%5d ", Count[group]);
printf ("%8.3f ", Sum[group]/Count[group]);
#define var(count,sum,ss) (count<=1) ? 0.0 : ((ss-sum*sum/count)/(count-1))
#define sd(count,sum,ss) sqrt (var (count,sum,ss))
printf ("%8.3f ", sd (Count[group], Sum[group], Sumsq[group]));
printf ("%8.3f ", Min[group]);
printf ("%8.3f ", Max[group]);
putchar ('\n');
}
}
/* compute one-way anova based on Guilford & Fruchter (5th Ed) p 239 */
oneway ()
{
double Gsum; /* grand sum */
double Gsumsq; /* grand sum of squares (SStotal) */
int Gcount; /* N total */
double SSn; /* will be sigma(i) Sum[i]*Sum[i]/Count[i] */
int dfbetween; /* degrees of freedom numerator */
int dfwithin; /* degrees of freedom denominator */
double SSbetween; /* sum of squares between groups */
double SSwithin; /* sum of squares within groups */
double MSbetween; /* mean square between groups */
double MSwithin; /* mean square within groups */
double F; /* F ratio */
double p, pof (); /* probability of F */
int group; /* loop index */
Gsum = Gsumsq = 0.0;
Gcount = 0;
for (group = 0; group < Ngroups; group++)
{
Gsum += Sum[group];
Gsumsq += Sumsq[group];
Gcount += Count[group];
}
if (Gcount <= Ngroups)
ERRMSG0 (You need more than one datum per group for comparison)
if (Ngroups < 2)
ERRMSG0 (You need at least two groups of data for a comparison)
SSn = 0.0;
for (group = 0; group < Ngroups; group++)
SSn += (Sum[group] * Sum[group]) / Count[group];
SSbetween = SSn - Gsum*Gsum/Gcount;
SSwithin = Gsumsq - SSn;
dfbetween = Ngroups - 1;
dfwithin = Gcount - Ngroups;
MSbetween = SSbetween / dfbetween;
MSwithin = SSwithin / dfwithin;
if (fzero (MSwithin))
{
F = 999.999;
p = 0.0;
}
else
{
F = MSbetween/MSwithin;
p = pof (F, dfbetween, dfwithin);
}
if (Ngroups == 2 && (Ttest || checkargv ("ttest", Argv0)))
printf ("t(%d) = %.3f p = %.3f\n", dfwithin, sqrt (F), p);
else
{
putchar ('\n');
printf ("%-8s %10s %5s %10s %8s %5s\n",
"Source", "SS", "df", "MS", "F", "p");
printf ("%-8s ", "Between");
printf ("%10.3f ", SSbetween);
printf ("%5d ", dfbetween);
printf ("%10.3f ", MSbetween);
printf ("%8.3f ", F);
printf ("%5.3f ", p);
if (p < .001) putchar ('*');
if (p < .01) putchar ('*');
if (p < .05) putchar ('*');
putchar ('\n');
printf ("%-8s ", "Within");
printf ("%10.3f ", SSwithin);
printf ("%5d ", dfwithin);
printf ("%10.3f ", MSwithin);
putchar ('\n');
}
}