Fixed the handling of MISSING values in t-test
authorJohn Darrington <john@darrington.wattle.id.au>
Sat, 13 Mar 2004 06:22:50 +0000 (06:22 +0000)
committerJohn Darrington <john@darrington.wattle.id.au>
Sat, 13 Mar 2004 06:22:50 +0000 (06:22 +0000)
15 files changed:
doc/pspp.texi
po/en_GB.po
po/pspp.pot
src/ChangeLog
src/levene.c
src/levene.h
src/t-test.q
src/var.h
tests/Makefile.am
tests/command/t-test-1-sample-missing-anal.sh [new file with mode: 0755]
tests/command/t-test-1-sample-missing-list.sh [new file with mode: 0755]
tests/command/t-test-indep-missing-anal.sh [new file with mode: 0755]
tests/command/t-test-indep-missing-list.sh [new file with mode: 0755]
tests/command/t-test-paired-missing-anal.sh [new file with mode: 0755]
tests/command/t-test-paired-missing-list.sh [new file with mode: 0755]

index 509efa6da2fa461f255efa9d24d997fab0c5bbbb..cda0308fd0aa9c87012c6f88796098ab9325337e 100644 (file)
@@ -7907,14 +7907,16 @@ in the tests.  The default value is 0.95.
 The @cmd{MISSING} subcommand determines the handling of missing
 variables.  
 If INCLUDE is set, then user-missing values are included in the
-calculations.  
+calculations, but system-missing values are not.
 If EXCLUDE is set, which is the default, user-missing
-values are excluded.  
-If LISTWISE is set, then
-the entire case is excluded whenever any value in that case has a
-system-missing or, if INCLUDE is set, user-missing value.
-If ANALYSIS is set, then cases are excluded only where a value used in
-the analysis has a system-missing or, if INCLUDE is set, user-missing value.
+values are excluded as well as system-missing values. 
+This is the default.
+
+If LISTWISE is set, then the entire case is excluded from analysis
+whenever any variable  specified in the @cmd{/VARIABLES}, @cmd{/PAIRS} or 
+@cmd{/GROUPS} subcommands contains a missing value.   
+If ANALYSIS is set, then missing values are excluded only in the analysis for
+which they would be needed. This is the default.
 
 
 @menu
@@ -7951,13 +7953,17 @@ The variable given in the @cmd{GROUPS} subcommand is the independent
 variable which determines to which group the samples belong.
 The values in parentheses are the specific values of the independent
 variable for each group.
-If the parentheses are omitted, and no values are given, the default values 
+If the parentheses are omitted and no values are given, the default values 
 of 1.0 and 2.0 are assumed.
-If only one value is given, then cases where the independent variable is
+
+If the independent variable is numeric, 
+it is acceptable to specify only one value inside the parentheses.
+If you do this, cases where the independent variable is
 less than  or equal to this value belong to the first group, and cases
 greater than this value belong to the second group.
-If only one value is given, then the independent variable must be
-numeric.
+When using this form of the @cmd{GROUPS} subcommand, missing values in
+the independent variable are excluded on a listwise basis, regardless
+of whether @cmd{/MISSING=LISTWISE} was specified.
 
 
 @node Paired Samples Mode, , Independent Samples Mode, T-TEST
index 43d5fa175a04022c070d54bb6782cadd018458f2..82622e7bb110a1af4fe99f0c2171f6d65b2d7179 100644 (file)
@@ -6,8 +6,8 @@
 msgid ""
 msgstr ""
 "Project-Id-Version: PSPP 0.3.1\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2004-03-12 16:21+0800\n"
+"Report-Msgid-Bugs-To: pspp-dev@gnu.org\n"
+"POT-Creation-Date: 2004-03-13 14:14+0800\n"
 "PO-Revision-Date: 2004-01-23 13:04+0800\n"
 "Last-Translator: John Darrington <john@darrington.wattle.id.au>\n"
 "Language-Team: John Darrington <john@darrington.wattle.id.au>\n"
@@ -4210,8 +4210,8 @@ msgstr ""
 msgid "Total"
 msgstr ""
 
-#: src/crosstabs.q:874 src/t-test.q:622 src/t-test.q:645 src/t-test.q:736
-#: src/t-test.q:1318
+#: src/crosstabs.q:874 src/t-test.q:655 src/t-test.q:678 src/t-test.q:769
+#: src/t-test.q:1343
 msgid "N"
 msgstr ""
 
@@ -4257,7 +4257,7 @@ msgstr ""
 msgid "Statistic"
 msgstr ""
 
-#: src/crosstabs.q:1159 src/t-test.q:889 src/t-test.q:1090 src/t-test.q:1202
+#: src/crosstabs.q:1159 src/t-test.q:920 src/t-test.q:1121 src/t-test.q:1227
 msgid "df"
 msgstr ""
 
@@ -4294,11 +4294,11 @@ msgstr ""
 msgid " 95%% Confidence Interval"
 msgstr ""
 
-#: src/crosstabs.q:1206 src/t-test.q:893 src/t-test.q:1087 src/t-test.q:1205
+#: src/crosstabs.q:1206 src/t-test.q:924 src/t-test.q:1118 src/t-test.q:1230
 msgid "Lower"
 msgstr ""
 
-#: src/crosstabs.q:1207 src/t-test.q:894 src/t-test.q:1088 src/t-test.q:1206
+#: src/crosstabs.q:1207 src/t-test.q:925 src/t-test.q:1119 src/t-test.q:1231
 msgid "Upper"
 msgstr ""
 
@@ -4435,8 +4435,8 @@ msgstr ""
 msgid "%s Dependent"
 msgstr ""
 
-#: src/descript.q:151 src/frequencies.q:94 src/t-test.q:623 src/t-test.q:646
-#: src/t-test.q:735 src/t-test.q:1084
+#: src/descript.q:151 src/frequencies.q:94 src/t-test.q:656 src/t-test.q:679
+#: src/t-test.q:768 src/t-test.q:1115
 msgid "Mean"
 msgstr ""
 
@@ -4978,157 +4978,157 @@ msgstr "Frame colour must be between 0 and 6."
 msgid "Drive letter expected in WORKDEV subcommand."
 msgstr ""
 
-#: src/t-test.q:208
+#: src/t-test.q:237
 msgid "TESTVAL, GROUPS and PAIRS subcommands are mutually exclusive."
 msgstr ""
 
-#: src/t-test.q:225
+#: src/t-test.q:254
 msgid "VARIABLES subcommand is not appropriate with PAIRS"
 msgstr ""
 
-#: src/t-test.q:317 src/t-test.q:396
+#: src/t-test.q:352 src/t-test.q:429
 #, c-format
 msgid "`%s' is not a variable name"
 msgstr ""
 
-#: src/t-test.q:330
+#: src/t-test.q:365
 #, c-format
 msgid "Long string variable %s is not valid here."
 msgstr ""
 
-#: src/t-test.q:347
+#: src/t-test.q:382
 msgid ""
 "When applying GROUPS to a string variable, at least one value must be "
 "specified."
 msgstr ""
 
-#: src/t-test.q:431
+#: src/t-test.q:464
 #, c-format
 msgid ""
 "PAIRED was specified but the number of variables preceding WITH (%d) did not "
 "match the number following (%d)."
 msgstr ""
 
-#: src/t-test.q:448
+#: src/t-test.q:481
 msgid "At least two variables must be specified on PAIRS."
 msgstr ""
 
-#: src/t-test.q:620
+#: src/t-test.q:653
 msgid "One-Sample Statistics"
 msgstr ""
 
-#: src/t-test.q:624 src/t-test.q:647 src/t-test.q:737 src/t-test.q:1085
+#: src/t-test.q:657 src/t-test.q:680 src/t-test.q:770 src/t-test.q:1116
 msgid "Std. Deviation"
 msgstr ""
 
-#: src/t-test.q:625 src/t-test.q:648 src/t-test.q:738
+#: src/t-test.q:658 src/t-test.q:681 src/t-test.q:771
 msgid "SE. Mean"
 msgstr ""
 
-#: src/t-test.q:642
+#: src/t-test.q:675
 msgid "Group Statistics"
 msgstr ""
 
-#: src/t-test.q:732
+#: src/t-test.q:765
 msgid "Paired Sample Statistics"
 msgstr ""
 
-#: src/t-test.q:754 src/t-test.q:1119 src/t-test.q:1339
+#: src/t-test.q:787 src/t-test.q:1144 src/t-test.q:1364
 #, c-format
 msgid "Pair %d"
 msgstr ""
 
-#: src/t-test.q:874
+#: src/t-test.q:905
 msgid "Independent Samples Test"
 msgstr ""
 
-#: src/t-test.q:882
+#: src/t-test.q:913
 msgid "Levene's Test for Equality of Variances"
 msgstr ""
 
-#: src/t-test.q:884
+#: src/t-test.q:915
 msgid "t-test for Equality of Means"
 msgstr ""
 
-#: src/t-test.q:886
+#: src/t-test.q:917
 msgid "F"
 msgstr ""
 
-#: src/t-test.q:887 src/t-test.q:1320
+#: src/t-test.q:918 src/t-test.q:1345
 msgid "Sig."
 msgstr ""
 
-#: src/t-test.q:888 src/t-test.q:1089 src/t-test.q:1201
+#: src/t-test.q:919 src/t-test.q:1120 src/t-test.q:1226
 msgid "t"
 msgstr ""
 
-#: src/t-test.q:890 src/t-test.q:1091 src/t-test.q:1203
+#: src/t-test.q:921 src/t-test.q:1122 src/t-test.q:1228
 msgid "Sig. (2-tailed)"
 msgstr ""
 
-#: src/t-test.q:891 src/t-test.q:1204
+#: src/t-test.q:922 src/t-test.q:1229
 msgid "Mean Difference"
 msgstr ""
 
-#: src/t-test.q:892
+#: src/t-test.q:923
 msgid "Std. Error Difference"
 msgstr ""
 
-#: src/t-test.q:897 src/t-test.q:1081 src/t-test.q:1196
+#: src/t-test.q:928 src/t-test.q:1112 src/t-test.q:1221
 #, c-format
 msgid "%d%% Confidence Interval of the Difference"
 msgstr ""
 
-#: src/t-test.q:931
+#: src/t-test.q:962
 msgid "Equal variances assumed"
 msgstr ""
 
-#: src/t-test.q:946
+#: src/t-test.q:977
 #, c-format
 msgid "Error calculating F statistic (cdff returned %d)."
 msgstr ""
 
-#: src/t-test.q:969 src/t-test.q:989 src/t-test.q:1027 src/t-test.q:1039
-#: src/t-test.q:1140 src/t-test.q:1166 src/t-test.q:1246 src/t-test.q:1263
-#: src/t-test.q:1354
+#: src/t-test.q:1000 src/t-test.q:1020 src/t-test.q:1058 src/t-test.q:1070
+#: src/t-test.q:1165 src/t-test.q:1191 src/t-test.q:1271 src/t-test.q:1288
+#: src/t-test.q:1377
 #, c-format
 msgid "Error calculating T statistic (cdft returned %d)."
 msgstr ""
 
-#: src/t-test.q:1003
+#: src/t-test.q:1034
 msgid "Equal variances not assumed"
 msgstr ""
 
-#: src/t-test.q:1071
+#: src/t-test.q:1102
 msgid "Paired Samples Test"
 msgstr ""
 
-#: src/t-test.q:1074
+#: src/t-test.q:1105
 msgid "Paired Differences"
 msgstr ""
 
-#: src/t-test.q:1086
+#: src/t-test.q:1117
 msgid "Std. Error Mean"
 msgstr ""
 
-#: src/t-test.q:1185
+#: src/t-test.q:1210
 msgid "One-Sample Test"
 msgstr ""
 
-#: src/t-test.q:1190
+#: src/t-test.q:1215
 #, c-format
 msgid "Test Value = %f"
 msgstr ""
 
-#: src/t-test.q:1315
+#: src/t-test.q:1340
 msgid "Paired Samples Correlations"
 msgstr ""
 
-#: src/t-test.q:1319
+#: src/t-test.q:1344
 msgid "Correlation"
 msgstr ""
 
-#: src/t-test.q:1342
+#: src/t-test.q:1367
 #, c-format
 msgid "%s & %s"
 msgstr ""
index d2a9fa36914314abf267649e22ba9eb5c0e408d3..d1039a6c97ef384eab0308d22fba1f4da85a3d77 100644 (file)
@@ -7,8 +7,8 @@
 msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2004-03-12 16:21+0800\n"
+"Report-Msgid-Bugs-To: pspp-dev@gnu.org\n"
+"POT-Creation-Date: 2004-03-13 14:14+0800\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -4211,8 +4211,8 @@ msgstr ""
 msgid "Total"
 msgstr ""
 
-#: src/crosstabs.q:874 src/t-test.q:622 src/t-test.q:645 src/t-test.q:736
-#: src/t-test.q:1318
+#: src/crosstabs.q:874 src/t-test.q:655 src/t-test.q:678 src/t-test.q:769
+#: src/t-test.q:1343
 msgid "N"
 msgstr ""
 
@@ -4258,7 +4258,7 @@ msgstr ""
 msgid "Statistic"
 msgstr ""
 
-#: src/crosstabs.q:1159 src/t-test.q:889 src/t-test.q:1090 src/t-test.q:1202
+#: src/crosstabs.q:1159 src/t-test.q:920 src/t-test.q:1121 src/t-test.q:1227
 msgid "df"
 msgstr ""
 
@@ -4295,11 +4295,11 @@ msgstr ""
 msgid " 95%% Confidence Interval"
 msgstr ""
 
-#: src/crosstabs.q:1206 src/t-test.q:893 src/t-test.q:1087 src/t-test.q:1205
+#: src/crosstabs.q:1206 src/t-test.q:924 src/t-test.q:1118 src/t-test.q:1230
 msgid "Lower"
 msgstr ""
 
-#: src/crosstabs.q:1207 src/t-test.q:894 src/t-test.q:1088 src/t-test.q:1206
+#: src/crosstabs.q:1207 src/t-test.q:925 src/t-test.q:1119 src/t-test.q:1231
 msgid "Upper"
 msgstr ""
 
@@ -4436,8 +4436,8 @@ msgstr ""
 msgid "%s Dependent"
 msgstr ""
 
-#: src/descript.q:151 src/frequencies.q:94 src/t-test.q:623 src/t-test.q:646
-#: src/t-test.q:735 src/t-test.q:1084
+#: src/descript.q:151 src/frequencies.q:94 src/t-test.q:656 src/t-test.q:679
+#: src/t-test.q:768 src/t-test.q:1115
 msgid "Mean"
 msgstr ""
 
@@ -4979,157 +4979,157 @@ msgstr ""
 msgid "Drive letter expected in WORKDEV subcommand."
 msgstr ""
 
-#: src/t-test.q:208
+#: src/t-test.q:237
 msgid "TESTVAL, GROUPS and PAIRS subcommands are mutually exclusive."
 msgstr ""
 
-#: src/t-test.q:225
+#: src/t-test.q:254
 msgid "VARIABLES subcommand is not appropriate with PAIRS"
 msgstr ""
 
-#: src/t-test.q:317 src/t-test.q:396
+#: src/t-test.q:352 src/t-test.q:429
 #, c-format
 msgid "`%s' is not a variable name"
 msgstr ""
 
-#: src/t-test.q:330
+#: src/t-test.q:365
 #, c-format
 msgid "Long string variable %s is not valid here."
 msgstr ""
 
-#: src/t-test.q:347
+#: src/t-test.q:382
 msgid ""
 "When applying GROUPS to a string variable, at least one value must be "
 "specified."
 msgstr ""
 
-#: src/t-test.q:431
+#: src/t-test.q:464
 #, c-format
 msgid ""
 "PAIRED was specified but the number of variables preceding WITH (%d) did not "
 "match the number following (%d)."
 msgstr ""
 
-#: src/t-test.q:448
+#: src/t-test.q:481
 msgid "At least two variables must be specified on PAIRS."
 msgstr ""
 
-#: src/t-test.q:620
+#: src/t-test.q:653
 msgid "One-Sample Statistics"
 msgstr ""
 
-#: src/t-test.q:624 src/t-test.q:647 src/t-test.q:737 src/t-test.q:1085
+#: src/t-test.q:657 src/t-test.q:680 src/t-test.q:770 src/t-test.q:1116
 msgid "Std. Deviation"
 msgstr ""
 
-#: src/t-test.q:625 src/t-test.q:648 src/t-test.q:738
+#: src/t-test.q:658 src/t-test.q:681 src/t-test.q:771
 msgid "SE. Mean"
 msgstr ""
 
-#: src/t-test.q:642
+#: src/t-test.q:675
 msgid "Group Statistics"
 msgstr ""
 
-#: src/t-test.q:732
+#: src/t-test.q:765
 msgid "Paired Sample Statistics"
 msgstr ""
 
-#: src/t-test.q:754 src/t-test.q:1119 src/t-test.q:1339
+#: src/t-test.q:787 src/t-test.q:1144 src/t-test.q:1364
 #, c-format
 msgid "Pair %d"
 msgstr ""
 
-#: src/t-test.q:874
+#: src/t-test.q:905
 msgid "Independent Samples Test"
 msgstr ""
 
-#: src/t-test.q:882
+#: src/t-test.q:913
 msgid "Levene's Test for Equality of Variances"
 msgstr ""
 
-#: src/t-test.q:884
+#: src/t-test.q:915
 msgid "t-test for Equality of Means"
 msgstr ""
 
-#: src/t-test.q:886
+#: src/t-test.q:917
 msgid "F"
 msgstr ""
 
-#: src/t-test.q:887 src/t-test.q:1320
+#: src/t-test.q:918 src/t-test.q:1345
 msgid "Sig."
 msgstr ""
 
-#: src/t-test.q:888 src/t-test.q:1089 src/t-test.q:1201
+#: src/t-test.q:919 src/t-test.q:1120 src/t-test.q:1226
 msgid "t"
 msgstr ""
 
-#: src/t-test.q:890 src/t-test.q:1091 src/t-test.q:1203
+#: src/t-test.q:921 src/t-test.q:1122 src/t-test.q:1228
 msgid "Sig. (2-tailed)"
 msgstr ""
 
-#: src/t-test.q:891 src/t-test.q:1204
+#: src/t-test.q:922 src/t-test.q:1229
 msgid "Mean Difference"
 msgstr ""
 
-#: src/t-test.q:892
+#: src/t-test.q:923
 msgid "Std. Error Difference"
 msgstr ""
 
-#: src/t-test.q:897 src/t-test.q:1081 src/t-test.q:1196
+#: src/t-test.q:928 src/t-test.q:1112 src/t-test.q:1221
 #, c-format
 msgid "%d%% Confidence Interval of the Difference"
 msgstr ""
 
-#: src/t-test.q:931
+#: src/t-test.q:962
 msgid "Equal variances assumed"
 msgstr ""
 
-#: src/t-test.q:946
+#: src/t-test.q:977
 #, c-format
 msgid "Error calculating F statistic (cdff returned %d)."
 msgstr ""
 
-#: src/t-test.q:969 src/t-test.q:989 src/t-test.q:1027 src/t-test.q:1039
-#: src/t-test.q:1140 src/t-test.q:1166 src/t-test.q:1246 src/t-test.q:1263
-#: src/t-test.q:1354
+#: src/t-test.q:1000 src/t-test.q:1020 src/t-test.q:1058 src/t-test.q:1070
+#: src/t-test.q:1165 src/t-test.q:1191 src/t-test.q:1271 src/t-test.q:1288
+#: src/t-test.q:1377
 #, c-format
 msgid "Error calculating T statistic (cdft returned %d)."
 msgstr ""
 
-#: src/t-test.q:1003
+#: src/t-test.q:1034
 msgid "Equal variances not assumed"
 msgstr ""
 
-#: src/t-test.q:1071
+#: src/t-test.q:1102
 msgid "Paired Samples Test"
 msgstr ""
 
-#: src/t-test.q:1074
+#: src/t-test.q:1105
 msgid "Paired Differences"
 msgstr ""
 
-#: src/t-test.q:1086
+#: src/t-test.q:1117
 msgid "Std. Error Mean"
 msgstr ""
 
-#: src/t-test.q:1185
+#: src/t-test.q:1210
 msgid "One-Sample Test"
 msgstr ""
 
-#: src/t-test.q:1190
+#: src/t-test.q:1215
 #, c-format
 msgid "Test Value = %f"
 msgstr ""
 
-#: src/t-test.q:1315
+#: src/t-test.q:1340
 msgid "Paired Samples Correlations"
 msgstr ""
 
-#: src/t-test.q:1319
+#: src/t-test.q:1344
 msgid "Correlation"
 msgstr ""
 
-#: src/t-test.q:1342
+#: src/t-test.q:1367
 #, c-format
 msgid "%s & %s"
 msgstr ""
index 396112149c7fbf80de7982ae76eff1086e87806f..7097fc14d4a0625aa45afd1af63d651fa28fe08d 100644 (file)
@@ -1,3 +1,8 @@
+Sat Mar 13 14:19:52 WST 2004 John Darrington <john@darrington.wattle.id.au>
+
+       * t-test.q, levene.c: Fixed up the handling of MISSING values
+       int the T-TEST
+
 Fri Mar 12 16:23:35 WST 2004 John Darrington <john@darrington.wattle.id.au>
 
        * t-test.q, levene.c: Added support for T-TEST /GROUP where only 
index 1666e0206a84ec76551323d4f010ecc6b311ab66..5617b7ba82db8ccc73f8cf72cd601f992ec18908 100644 (file)
@@ -83,18 +83,27 @@ struct levene_info
   /* The dependent variables */
   struct variable  **v_dep;
 
+  /* How to treat missing values */
+  enum lev_missing missing;
+
+  /* Function to test for missing values */
+  is_missing_func is_missing;
+
 };
 
 
 
 void  
-levene(struct variable *v_indep, int n_dep, struct variable **v_dep)
+levene(struct variable *v_indep, int n_dep, struct variable **v_dep,
+            enum lev_missing missing,   is_missing_func value_is_missing)
 {
   struct levene_info l;
 
-  l.n_dep=n_dep;
-  l.v_indep=v_indep;
-  l.v_dep=v_dep;
+  l.n_dep = n_dep;
+  l.v_indep = v_indep;
+  l.v_dep = v_dep;
+  l.missing = missing;
+  l.is_missing = value_is_missing;
 
   procedure(levene_precalc, levene_calc, levene_postcalc, &l);
   procedure(levene2_precalc,levene2_calc,levene2_postcalc,&l);
@@ -203,32 +212,50 @@ levene_precalc (void *_l)
 static int 
 levene_calc (struct ccase *c, void *_l)
 {
-  int var;
+  int i;
   struct levene_info *l = (struct levene_info *) _l;
   union value *gv = &c->data[l->v_indep->fv];
   struct group_statistics key;
   double weight = dict_get_case_weight(default_dict,c); 
+
+
+  /* Skip the entire case if /MISSING=LISTWISE is set */
+  if ( l->missing == LEV_LISTWISE ) 
+    {
+      for (i = 0; i < l->n_dep; ++i) 
+       {
+         struct variable *v = l->v_dep[i];
+         union value *val = &c->data[v->fv];
+
+         if (l->is_missing(val,v) )
+           {
+             return 0;
+           }
+       }
+    }
+
   
   key.id = *gv;
   key.criterion = CMP_EQ;
 
-  for (var = 0; var < l->n_dep; ++var
+  for (i = 0; i < l->n_dep; ++i
     {
+      struct variable *var = l->v_dep[i];
       double levene_z;
-      union value *v = &c->data[l->v_dep[var]->fv];
+      union value *v = &c->data[var->fv];
       struct group_statistics *gs;
-      gs = get_group(var,&key); 
+      gs = get_group(i,&key); 
       if ( 0 == gs ) 
        continue ;
 
-      /* FIXME: handle SYSMIS properly */
-
-      levene_z= fabs(v->f - gs->mean);
-      lz[var].grand_total += levene_z * weight;
-      lz[var].total_n += weight; 
-
-      gs->lz_total += levene_z * weight;
+      if ( ! l->is_missing(v,var))
+       {
+         levene_z= fabs(v->f - gs->mean);
+         lz[i].grand_total += levene_z * weight;
+         lz[i].total_n += weight; 
 
+         gs->lz_total += levene_z * weight;
+       }
     }
   return 0;
 }
@@ -280,7 +307,7 @@ levene2_precalc (void *_l)
 static int 
 levene2_calc (struct ccase *c, void *_l)
 {
-  int var;
+  int i;
 
   struct levene_info *l = (struct levene_info *) _l;
 
@@ -289,23 +316,39 @@ levene2_calc (struct ccase *c, void *_l)
   union value *gv = &c->data[l->v_indep->fv];
   struct group_statistics key;
 
+  /* Skip the entire case if /MISSING=LISTWISE is set */
+  if ( l->missing == LEV_LISTWISE ) 
+    {
+      for (i = 0; i < l->n_dep; ++i) 
+       {
+         struct variable *v = l->v_dep[i];
+         union value *val = &c->data[v->fv];
+
+         if (l->is_missing(val,v) )
+           {
+             return 0;
+           }
+       }
+    }
+
   key.id = *gv;
   key.criterion = CMP_EQ;
 
-  for (var = 0; var < l->n_dep; ++var
+  for (i = 0; i < l->n_dep; ++i
     {
       double levene_z;
-      union value *v = &c->data[l->v_dep[var]->fv];
+      struct variable *var = l->v_dep[i] ;
+      union value *v = &c->data[var->fv];
       struct group_statistics *gs;
-      gs = get_group(var,&key); 
+      gs = get_group(i,&key); 
       if ( 0 == gs ) 
        continue;
 
-      /* FIXME: handle SYSMIS properly */
-
-      levene_z = fabs(v->f - gs->mean); 
-
-      lz_denominator[var] += weight * sqr(levene_z - gs->lz_mean);
+      if ( ! l->is_missing(v,var) )
+       {
+         levene_z = fabs(v->f - gs->mean); 
+         lz_denominator[i] += weight * sqr(levene_z - gs->lz_mean);
+       }
     }
 
   return 0;
index 8f19deade2a33237648bf9f339ee50e727be2deb..37019524408d27e206c81bb54fa655818ebe96cd 100644 (file)
@@ -25,6 +25,8 @@
 
 #include "var.h"
 
+/* What to do with missing values */
+enum lev_missing { LEV_ANALYSIS, LEV_LISTWISE };
 
 /* Calculate the Levene statistic 
 
@@ -36,7 +38,9 @@ The dependent variables :   v_dep;
 
 */
 
-void  levene(struct variable *v_indep, int n_dep, struct variable **v_dep);
+
+void  levene(struct variable *v_indep, int n_dep, struct variable **v_dep,
+            enum lev_missing,   is_missing_func);
 
 
 
index f9012555fbedaaa617b0f4cd6bf44d8508ff614a..2f8cd6fab0ff3ee9da4b0a8ee2b91ffd607439f2 100644 (file)
 /* (declarations) */
 /* (functions) */
 
+
 static struct cmd_t_test cmd;
 
+/* Function to use for testing for missing values */
+static is_missing_func value_is_missing;
+
 /* Variable for the GROUPS subcommand, if given. */
 static struct variable *indep_var;
 
@@ -68,12 +72,34 @@ static union value groups_values[2];
 static enum comparison criteria[2];
 
 
+
 /* PAIRS: Number of pairs to be compared ; each pair. */
 static int n_pairs = 0 ;
 struct pair 
 {
+#if 1
   /* The variables comprising the pair */
   struct variable *v[2];
+#endif
+
+  /* The number of valid variable pairs */
+  double n;
+
+  /* The sum of the members */
+  double sum[2];
+
+  /* sum of squares of the members */
+  double ssq[2];
+
+  /* Std deviation of the members */
+  double std_dev[2];
+
+
+  /* Sample Std deviation of the members */
+  double s_std_dev[2];
+
+  /* The means of the members */
+  double mean[2];
 
   /* The correlation coefficient between the variables */
   double correlation;
@@ -81,6 +107,9 @@ struct pair
   /* The sum of the differences */
   double sum_of_diffs;
 
+  /* The sum of the products */
+  double sum_of_prod;
+
   /* The mean of the differences */
   double mean_diff;
 
@@ -258,6 +287,11 @@ cmd_t_test(void)
        }
     }
 
+  /* If /MISSING=INCLUDE is set, then user missing values are ignored */
+  if (cmd.incl == TTS_INCLUDE ) 
+    value_is_missing = is_system_missing;
+  else
+    value_is_missing = is_missing;
 
   procedure(common_precalc,common_calc,common_postcalc, NULL);
 
@@ -271,7 +305,9 @@ cmd_t_test(void)
       break;
     case T_IND_SAMPLES:
       procedure(group_precalc,group_calc,group_postcalc, NULL);
-      levene(indep_var, cmd.n_variables, cmd.v_variables);
+      levene(indep_var, cmd.n_variables, cmd.v_variables,
+            (cmd.miss == TTS_LISTWISE)?LEV_LISTWISE:LEV_ANALYSIS ,
+            value_is_missing);
       break;
     }
 
@@ -290,7 +326,6 @@ cmd_t_test(void)
   free(pairs);
   pairs=0;
 
-
   if ( mode == T_IND_SAMPLES) 
     {
       int i;
@@ -375,8 +410,6 @@ tts_custom_groups (struct cmd_t_test *cmd UNUSED)
 }
 
 
-
-
 static int
 tts_custom_pairs (struct cmd_t_test *cmd UNUSED)
 {
@@ -764,15 +797,13 @@ ssbox_paired_populate(struct ssbox *ssb,struct cmd_t_test *cmd UNUSED)
          tab_text (ssb->t, 1, i*2+j+1, TAB_LEFT, pairs[i].v[j]->name);
 
          /* Values */
-         tab_float (ssb->t,2, i*2+j+1, TAB_RIGHT, gs->mean, 8, 2);
-         tab_float (ssb->t,3, i*2+j+1, TAB_RIGHT, gs->n, 2, 0);
-         tab_float (ssb->t,4, i*2+j+1, TAB_RIGHT, gs->std_dev, 8, 3);
-         tab_float (ssb->t,5, i*2+j+1, TAB_RIGHT, gs->se_mean, 8, 3);
+         tab_float (ssb->t,2, i*2+j+1, TAB_RIGHT, pairs[i].mean[j], 8, 2);
+         tab_float (ssb->t,3, i*2+j+1, TAB_RIGHT, pairs[i].n, 2, 0);
+         tab_float (ssb->t,4, i*2+j+1, TAB_RIGHT, pairs[i].std_dev[j], 8, 3);
+         tab_float (ssb->t,5, i*2+j+1, TAB_RIGHT, pairs[i].std_dev[j]/sqrt(pairs[i].n), 8, 3);
 
        }
-
     }
-
 }
 
 /* Populate the one sample ssbox */
@@ -1106,13 +1137,7 @@ trbox_paired_populate(struct trbox *trb,
       double bound;
       double se_mean;
 
-      struct variable *v0 = pairs[i].v[0];
-      struct variable *v1 = pairs[i].v[1];
-
-      struct group_statistics *gs0 = &v0->p.t_t.ugs;
-      struct group_statistics *gs1 = &v1->p.t_t.ugs;
-
-      double n = gs0->n;
+      double n = pairs[i].n;
       double t;
       double df = n - 1;
       
@@ -1146,12 +1171,13 @@ trbox_paired_populate(struct trbox *trb,
       tab_float(trb->t, 6, i+3, TAB_RIGHT, 
                pairs[i].mean_diff + t * se_mean , 8, 4); 
 
-      t = ( gs0->mean - gs1->mean)
-       / sqrt ( 
-               (  sqr(gs0->s_std_dev) + sqr(gs1->s_std_dev)  - 
-                  2 * pairs[i].correlation * gs0->s_std_dev * gs1->s_std_dev              )
-               / (n-1) )
-       ;
+      t = (pairs[i].mean[0] - pairs[i].mean[1])
+       / sqrt (
+               ( sqr (pairs[i].s_std_dev[0]) + sqr (pairs[i].s_std_dev[1]) -
+                 2 * pairs[i].correlation * 
+                 pairs[i].s_std_dev[0] * pairs[i].s_std_dev[1] )
+               / (n - 1)
+               );
 
       tab_float(trb->t, 7, i+3, TAB_RIGHT, t , 8,3 );
 
@@ -1160,7 +1186,6 @@ trbox_paired_populate(struct trbox *trb,
 
       which=1;
       cdft(&which, &p, &q, &t, &df, &status, &bound);
-
       if ( 0 != status )
        {
          msg( SE, _("Error calculating T statistic (cdft returned %d)."),status);
@@ -1327,7 +1352,7 @@ pscbox(void)
       int status;
       double bound;
 
-      double df = pairs[i].v[0]->p.t_t.ugs.n -2;
+      double df = pairs[i].n -2;
 
       double correlation_t = 
        pairs[i].correlation * sqrt(df) /
@@ -1343,20 +1368,16 @@ pscbox(void)
 
 
       /* row data */
+      tab_float(table, 2, i+1, TAB_RIGHT, pairs[i].n, 4, 0);
       tab_float(table, 3, i+1, TAB_RIGHT, pairs[i].correlation, 8, 3);
-      tab_float(table, 2, i+1, TAB_RIGHT, pairs[i].v[0]->p.t_t.ugs.n , 4, 0);
-
 
       cdft(&which, &p, &q, &correlation_t, &df, &status, &bound);
-
       if ( 0 != status )
        {
          msg( SE, _("Error calculating T statistic (cdft returned %d)."),status);
        }
 
-
       tab_float(table, 4, i+1, TAB_RIGHT, 2.0*(correlation_t>0?q:p), 8, 3);
-      
     }
 
   tab_submit(table);
@@ -1374,6 +1395,33 @@ common_calc (struct ccase *c, void *aux UNUSED)
 
   double weight = dict_get_case_weight(default_dict,c);
 
+
+  /* Skip the entire case if /MISSING=LISTWISE is set */
+  if ( cmd.miss == TTS_LISTWISE ) 
+    {
+      for(i=0; i< cmd.n_variables ; ++i) 
+       {
+         struct variable *v = cmd.v_variables[i];
+         union value *val = &c->data[v->fv];
+
+         if (value_is_missing(val,v) )
+           {
+             return 0;
+           }
+       }
+    }
+
+  /* Listwise has to be implicit if the independent variable is missing ?? */
+  if ( cmd.sbc_groups )
+    {
+      union value *gv = &c->data[indep_var->fv];
+      if ( value_is_missing(gv,indep_var) )
+       {
+         return 0;
+       }
+    }
+
+
   for(i=0; i< cmd.n_variables ; ++i) 
     {
       struct group_statistics *gs;
@@ -1382,7 +1430,7 @@ common_calc (struct ccase *c, void *aux UNUSED)
 
       gs= &cmd.v_variables[i]->p.t_t.ugs;
 
-      if (val->f != SYSMIS) 
+      if (! value_is_missing(val,v) )
        {
          gs->n+=weight;
          gs->sum+=weight * val->f;
@@ -1444,6 +1492,21 @@ one_sample_calc (struct ccase *c, void *aux UNUSED)
 
   double weight = dict_get_case_weight(default_dict,c);
 
+  /* Skip the entire case if /MISSING=LISTWISE is set */
+  if ( cmd.miss == TTS_LISTWISE ) 
+    {
+      for(i=0; i< cmd.n_variables ; ++i) 
+       {
+         struct variable *v = cmd.v_variables[i];
+         union value *val = &c->data[v->fv];
+
+         if (value_is_missing(val,v) )
+           {
+             return 0;
+           }
+       }
+    }
+
   for(i=0; i< cmd.n_variables ; ++i) 
     {
       struct group_statistics *gs;
@@ -1452,7 +1515,7 @@ one_sample_calc (struct ccase *c, void *aux UNUSED)
 
       gs= &cmd.v_variables[i]->p.t_t.ugs;
       
-      if (val->f != SYSMIS) 
+      if ( ! value_is_missing(val,v))
        gs->sum_diff += weight * (val->f - cmd.n_testval);
     }
 
@@ -1518,9 +1581,13 @@ paired_precalc (void *aux UNUSED)
 
   for(i=0; i < n_pairs ; ++i )
     {
-      pairs[i].correlation=0;
-      pairs[i].sum_of_diffs=0;
-      pairs[i].ssq_diffs=0;
+      pairs[i].n = 0;
+      pairs[i].sum[0] = 0;      pairs[i].sum[1] = 0;
+      pairs[i].ssq[0] = 0;      pairs[i].ssq[1] = 0;
+      pairs[i].sum_of_prod = 0;
+      pairs[i].correlation = 0;
+      pairs[i].sum_of_diffs = 0;
+      pairs[i].ssq_diffs = 0;
     }
 
 }
@@ -1531,6 +1598,28 @@ paired_calc (struct ccase *c, void *aux UNUSED)
 {
   int i;
 
+  double weight = dict_get_case_weight(default_dict,c);
+
+  /* Skip the entire case if /MISSING=LISTWISE is set , 
+   AND one member of a pair is missing */
+  if ( cmd.miss == TTS_LISTWISE ) 
+    {
+      for(i=0; i < n_pairs ; ++i )
+       {
+         struct variable *v0 = pairs[i].v[0];
+         struct variable *v1 = pairs[i].v[1];
+
+         union value *val0 = &c->data[v0->fv];
+         union value *val1 = &c->data[v1->fv];
+         
+         if ( value_is_missing(val0,v0) ||
+              value_is_missing(val1,v1) )
+           {
+             return 0;
+           }
+       }
+    }
+
   for(i=0; i < n_pairs ; ++i )
     {
       struct variable *v0 = pairs[i].v[0];
@@ -1539,13 +1628,28 @@ paired_calc (struct ccase *c, void *aux UNUSED)
       union value *val0 = &c->data[v0->fv];
       union value *val1 = &c->data[v1->fv];
 
-      pairs[i].correlation += ( val0->f - pairs[i].v[0]->p.t_t.ugs.mean )
-                             *
-                             ( val1->f - pairs[i].v[1]->p.t_t.ugs.mean );
+      if ( ( !value_is_missing(val0,v0) && !value_is_missing(val1,v1) ) )
+      {
+       pairs[i].n += weight;
+       pairs[i].sum[0] += weight * val0->f;
+       pairs[i].sum[1] += weight * val1->f;
+
+       pairs[i].ssq[0] += weight * sqr(val0->f);
+       pairs[i].ssq[1] += weight * sqr(val1->f);
 
-      pairs[i].sum_of_diffs += val0->f - val1->f ;
-      pairs[i].ssq_diffs += sqr(val0->f - val1->f);
+#if 0
+       pairs[i].correlation += weight * 
+         ( val0->f - pairs[i].v[0]->p.t_t.ugs.mean )
+         *
+         ( val1->f - pairs[i].v[1]->p.t_t.ugs.mean );
+#endif
 
+       pairs[i].sum_of_prod += weight * val0->f * val1->f ;
+
+
+       pairs[i].sum_of_diffs += weight * ( val0->f - val1->f ) ;
+       pairs[i].ssq_diffs += weight * sqr(val0->f - val1->f);
+      }
     }
 
   return 0;
@@ -1558,11 +1662,33 @@ paired_postcalc (void *aux UNUSED)
 
   for(i=0; i < n_pairs ; ++i )
     {
-      const double n = pairs[i].v[0]->p.t_t.ugs.n ;
+      int j;
+      const double n = pairs[i].n;
+
+      for (j=0; j < 2 ; ++j) 
+       {
+         pairs[i].mean[j] = pairs[i].sum[j] / n ;
+         pairs[i].s_std_dev[j] = sqrt((pairs[i].ssq[j] / n - 
+                                             sqr(pairs[i].mean[j]))
+                                    );
+
+         pairs[i].std_dev[j] = sqrt(n/(n-1)*(pairs[i].ssq[j] / n - 
+                                             sqr(pairs[i].mean[j]))
+                                    );
+       }
+      
+      pairs[i].correlation = pairs[i].sum_of_prod / pairs[i].n - 
+       pairs[i].mean[0] * pairs[i].mean[1] ;
+      /* correlation now actually contains the covariance */
       
+      pairs[i].correlation /= pairs[i].std_dev[0] * pairs[i].std_dev[1];
+      pairs[i].correlation *= pairs[i].n / ( pairs[i].n - 1 );
+      
+#if 0
       pairs[i].correlation /= pairs[i].v[0]->p.t_t.ugs.std_dev * 
                               pairs[i].v[1]->p.t_t.ugs.std_dev ;
-      pairs[i].correlation /= pairs[i].v[0]->p.t_t.ugs.n -1; 
+      pairs[i].correlation /= n - 1; 
+#endif      
 
 
       pairs[i].mean_diff = pairs[i].sum_of_diffs / n ;
@@ -1653,6 +1779,26 @@ group_calc (struct ccase *c, void *aux UNUSED)
 
   double weight = dict_get_case_weight(default_dict,c);
 
+  if ( value_is_missing(gv,indep_var) )
+    {
+      return 0;
+    }
+
+  if ( cmd.miss == TTS_LISTWISE ) 
+    {
+      for(i=0; i< cmd.n_variables ; ++i) 
+       {
+         struct variable *v = cmd.v_variables[i];
+         union value *val = &c->data[v->fv];
+
+         if (value_is_missing(val,v) )
+           {
+             return 0;
+           }
+       }
+    }
+
+
   gv = &c->data[indep_var->fv];
 
   g = get_group(gv,indep_var);
@@ -1664,13 +1810,18 @@ group_calc (struct ccase *c, void *aux UNUSED)
 
   for(i=0; i< cmd.n_variables ; ++i) 
     {
-      struct group_statistics *gs = &cmd.v_variables[i]->p.t_t.gs[g];
+      struct variable *var = cmd.v_variables[i];
 
-      union value *val=&c->data[cmd.v_variables[i]->fv];
+      struct group_statistics *gs = &var->p.t_t.gs[g];
 
-      gs->n+=weight;
-      gs->sum+=weight * val->f;
-      gs->ssq+=weight * sqr(val->f);
+      union value *val=&c->data[var->fv];
+
+      if ( !value_is_missing(val,var) )
+       {
+         gs->n+=weight;
+         gs->sum+=weight * val->f;
+         gs->ssq+=weight * sqr(val->f);
+       }
     }
 
   return 0;
index 11add5b0daa99ecc7600c0e1bcb1207b3ee80469..60298513c4c61fc3c127cd799aa984944deb8b7e 100644 (file)
--- a/src/var.h
+++ b/src/var.h
@@ -405,6 +405,7 @@ void cancel_temporary (void);
 /* Functions. */
 
 void dump_split_vars (const struct ccase *);
+typedef int (* is_missing_func )(const union value *, const struct variable *);
 
 int is_num_user_missing (double, const struct variable *);
 int is_str_user_missing (const unsigned char[], const struct variable *);
index 229b5e06e8d67b8fe63ae4746cc35e180e6c8ff2..32d838aa2b409f377474e73b9c5660f1c8ad050e 100644 (file)
@@ -25,6 +25,12 @@ TESTS = command/aggregate.sh \
        command/t-test-pairs.sh \
        command/t-test-groups.sh \
        command/t-test-1-indep-val.sh \
+       command/t-test-1-sample-missing-list.sh \
+       command/t-test-paired-missing-list.sh \
+       command/t-test-paired-missing-anal.sh \
+       command/t-test-1-sample-missing-anal.sh \
+       command/t-test-indep-missing-list.sh \
+       command/t-test-indep-missing-anal.sh \
        command/weight.sh \
        bugs/alpha-freq.sh \
        bugs/compute-fmt.sh \
diff --git a/tests/command/t-test-1-sample-missing-anal.sh b/tests/command/t-test-1-sample-missing-anal.sh
new file mode 100755 (executable)
index 0000000..bd6a224
--- /dev/null
@@ -0,0 +1,101 @@
+#!/bin/sh
+
+# This program tests that the T-TEST /TESTVAL command works OK
+# when there are per analysis missing values involved.
+
+TEMPDIR=/tmp/pspp-tst-$$
+
+here=`pwd`;
+
+# ensure that top_srcdir is absolute
+cd $top_srcdir; top_srcdir=`pwd`
+
+export STAT_CONFIG_PATH=$top_srcdir/config
+
+
+cleanup()
+{
+     rm -rf $TEMPDIR
+}
+
+
+fail()
+{
+    echo $activity
+    echo FAILED
+    cleanup;
+    exit 1;
+}
+
+
+no_result()
+{
+    echo $activity
+    echo NO RESULT;
+    cleanup;
+    exit 2;
+}
+
+pass()
+{
+    cleanup;
+    exit 0;
+}
+
+mkdir -p $TEMPDIR
+
+cd $TEMPDIR
+
+activity="create program 1"
+cat > $TEMPDIR/out.stat <<EOF
+data list list /id * x1 * x2.
+begin data.
+1 3.5 34
+2 2.0 10
+3 2.0 23
+4 3.5 98
+5 3.0 23
+67 4.0 8
+end data.
+
+t-test /testval=3.0 /var=x1 x2.
+EOF
+if [ $? -ne 0 ] ; then no_result ; fi
+
+
+activity="run program 1"
+$here/../src/pspp -o raw-ascii $TEMPDIR/out.stat
+if [ $? -ne 0 ] ; then no_result ; fi
+
+activity="copy output"
+cp $TEMPDIR/pspp.list $TEMPDIR/ref.list
+if [ $? -ne 0 ] ; then no_result ; fi
+
+
+activity="create program 2"
+cat > $TEMPDIR/out.stat <<EOF
+data list list /id * x1 * x2.
+begin data.
+1 3.5 34
+2 2.0 10
+3 2.0 23
+4 3.5 98
+5 3.0 23
+6 4.0 .
+7  .  8
+end data.
+
+t-test /missing=analysis /testval=3.0 /var=x1 x2.
+EOF
+if [ $? -ne 0 ] ; then no_result ; fi
+
+activity="run program 2"
+$here/../src/pspp -o raw-ascii $TEMPDIR/out.stat
+if [ $? -ne 0 ] ; then no_result ; fi
+
+activity="compare outputs"
+diff $TEMPDIR/ref.list $TEMPDIR/pspp.list
+if [ $? -ne 0 ] ; then fail ; fi
+
+
+pass
diff --git a/tests/command/t-test-1-sample-missing-list.sh b/tests/command/t-test-1-sample-missing-list.sh
new file mode 100755 (executable)
index 0000000..437725d
--- /dev/null
@@ -0,0 +1,101 @@
+#!/bin/sh
+
+# This program tests that the T-TEST /TESTVAL command works OK
+# when there are listwise missing values involved.
+
+TEMPDIR=/tmp/pspp-tst-$$
+
+here=`pwd`;
+
+# ensure that top_srcdir is absolute
+cd $top_srcdir; top_srcdir=`pwd`
+
+export STAT_CONFIG_PATH=$top_srcdir/config
+
+
+cleanup()
+{
+     rm -rf $TEMPDIR
+}
+
+
+fail()
+{
+    echo $activity
+    echo FAILED
+    cleanup;
+    exit 1;
+}
+
+
+no_result()
+{
+    echo $activity
+    echo NO RESULT;
+    cleanup;
+    exit 2;
+}
+
+pass()
+{
+    cleanup;
+    exit 0;
+}
+
+mkdir -p $TEMPDIR
+
+cd $TEMPDIR
+
+activity="create program 1"
+cat > $TEMPDIR/out.stat <<EOF
+data list list /id * x1 * x2.
+begin data.
+1 3.5 34
+2 2.0 10
+3 2.0 23
+4 3.5 98
+5 3.0 23
+end data.
+
+t-test /testval=3.0 /var=x1 x2.
+EOF
+if [ $? -ne 0 ] ; then no_result ; fi
+
+
+activity="run program 1"
+$here/../src/pspp -o raw-ascii $TEMPDIR/out.stat
+if [ $? -ne 0 ] ; then no_result ; fi
+
+activity="copy output"
+cp $TEMPDIR/pspp.list $TEMPDIR/ref.list
+if [ $? -ne 0 ] ; then no_result ; fi
+
+
+activity="create program 2"
+cat > $TEMPDIR/out.stat <<EOF
+data list list /id * x1 * x2.
+begin data.
+1 3.5 34
+2 2.0 10
+3 2.0 23
+4 3.5 98
+5 3.0 23
+6 4.0 99
+end data.
+
+MISSING VALUES x2(99).
+
+t-test /missing=listwise /testval=3.0 /var=x1 x2.
+EOF
+if [ $? -ne 0 ] ; then no_result ; fi
+
+activity="run program 2"
+$here/../src/pspp -o raw-ascii $TEMPDIR/out.stat
+if [ $? -ne 0 ] ; then no_result ; fi
+
+activity="compare outputs"
+diff $TEMPDIR/ref.list $TEMPDIR/pspp.list
+if [ $? -ne 0 ] ; then fail ; fi
+
+
+pass
diff --git a/tests/command/t-test-indep-missing-anal.sh b/tests/command/t-test-indep-missing-anal.sh
new file mode 100755 (executable)
index 0000000..4c38822
--- /dev/null
@@ -0,0 +1,103 @@
+#!/bin/sh
+
+# This program tests that the T-TEST /GROUPS command works OK
+# when ANALYSIS missing values are involved
+
+TEMPDIR=/tmp/pspp-tst-$$
+
+here=`pwd`;
+
+# ensure that top_srcdir is absolute
+cd $top_srcdir; top_srcdir=`pwd`
+
+export STAT_CONFIG_PATH=$top_srcdir/config
+
+
+cleanup()
+{
+     rm -rf $TEMPDIR
+}
+
+
+fail()
+{
+    echo $activity
+    echo FAILED
+    cleanup;
+    exit 1;
+}
+
+
+no_result()
+{
+    echo $activity
+    echo NO RESULT;
+    cleanup;
+    exit 2;
+}
+
+pass()
+{
+    cleanup;
+    exit 0;
+}
+
+mkdir -p $TEMPDIR
+
+cd $TEMPDIR
+
+activity="create program 1"
+cat > $TEMPDIR/out.stat <<EOF
+data list list /id * indep * dep1 * dep2 *.
+begin data.
+1  1.0 3.5 6
+2  1.0 2.0 5
+3  1.0 2.0 4
+4  2.0 3.5 3
+56 2.0 3.0 1
+end data.
+
+t-test /group=indep /var=dep1, dep2.
+EOF
+if [ $? -ne 0 ] ; then no_result ; fi
+
+
+activity="run program 1"
+$here/../src/pspp -o raw-ascii $TEMPDIR/out.stat
+if [ $? -ne 0 ] ; then no_result ; fi
+
+activity="copy output"
+cp $TEMPDIR/pspp.list $TEMPDIR/ref.list
+if [ $? -ne 0 ] ; then no_result ; fi
+
+activity="create program 2"
+cat > $TEMPDIR/out.stat <<EOF
+data list list /id * indep * dep1 * dep2.
+begin data.
+1 1.0 3.5 6
+2 1.0 2.0 5
+3 1.0 2.0 4
+4 2.0 3.5 3
+5 2.0 3.0 .
+6 2.0 .   1
+7  .  3.1 5
+end data.
+
+* Note that if the independent variable is missing, then it's implicitly 
+* listwise missing.
+
+t-test /missing=analysis /group=indep /var=dep1 dep2.
+EOF
+if [ $? -ne 0 ] ; then no_result ; fi
+
+activity="run program 2"
+$here/../src/pspp -o raw-ascii $TEMPDIR/out.stat
+if [ $? -ne 0 ] ; then no_result ; fi
+
+
+activity="compare outputs"
+diff $TEMPDIR/ref.list $TEMPDIR/pspp.list 
+if [ $? -ne 0 ] ; then fail ; fi
+
+
+pass
diff --git a/tests/command/t-test-indep-missing-list.sh b/tests/command/t-test-indep-missing-list.sh
new file mode 100755 (executable)
index 0000000..0a807cc
--- /dev/null
@@ -0,0 +1,101 @@
+#!/bin/sh
+
+# This program tests that the T-TEST /GROUPS command works OK
+# when LISTWISE missing values are involved
+
+TEMPDIR=/tmp/pspp-tst-$$
+
+here=`pwd`;
+
+# ensure that top_srcdir is absolute
+cd $top_srcdir; top_srcdir=`pwd`
+
+export STAT_CONFIG_PATH=$top_srcdir/config
+
+
+cleanup()
+{
+     rm -rf $TEMPDIR
+}
+
+
+fail()
+{
+    echo $activity
+    echo FAILED
+    cleanup;
+    exit 1;
+}
+
+
+no_result()
+{
+    echo $activity
+    echo NO RESULT;
+    cleanup;
+    exit 2;
+}
+
+pass()
+{
+    cleanup;
+    exit 0;
+}
+
+mkdir -p $TEMPDIR
+
+cd $TEMPDIR
+
+activity="create program 1"
+cat > $TEMPDIR/out.stat <<EOF
+data list list /id * indep * dep1 * dep2.
+begin data.
+1 1.0 3.5 6
+2 1.0 2.0 5
+3 1.0 2.0 4
+4 2.0 3.5 3
+5 2.0 3.0 2
+6 2.0 4.0 1
+end data.
+
+t-test /group=indep /var=dep1 dep2.
+EOF
+if [ $? -ne 0 ] ; then no_result ; fi
+
+
+activity="run program 1"
+$here/../src/pspp -o raw-ascii $TEMPDIR/out.stat
+if [ $? -ne 0 ] ; then no_result ; fi
+
+activity="copy output"
+cp $TEMPDIR/pspp.list $TEMPDIR/ref.list
+if [ $? -ne 0 ] ; then no_result ; fi
+
+activity="create program 2"
+cat > $TEMPDIR/out.stat <<EOF
+data list list /id * indep * dep1 * dep2 *.
+begin data.
+1 1.0 3.5 6
+2 1.0 2.0 5
+3 1.0 2.0 4
+4 2.0 3.5 3
+5 2.0 3.0 2
+6 2.0 4.0 1
+7 2.0 .   0
+end data.
+
+t-test /missing=listwise,exclude /group=indep /var=dep1, dep2.
+EOF
+if [ $? -ne 0 ] ; then no_result ; fi
+
+activity="run program 2"
+$here/../src/pspp -o raw-ascii $TEMPDIR/out.stat
+if [ $? -ne 0 ] ; then no_result ; fi
+
+
+activity="compare outputs"
+diff $TEMPDIR/ref.list $TEMPDIR/pspp.list 
+if [ $? -ne 0 ] ; then fail ; fi
+
+
+pass
diff --git a/tests/command/t-test-paired-missing-anal.sh b/tests/command/t-test-paired-missing-anal.sh
new file mode 100755 (executable)
index 0000000..a4ac3b9
--- /dev/null
@@ -0,0 +1,101 @@
+#!/bin/sh
+
+# This program tests that the T-TEST /PAIRS command works OK
+# when there is per ANALYSIS missing data involved.
+
+TEMPDIR=/tmp/pspp-tst-$$
+
+here=`pwd`;
+
+# ensure that top_srcdir is absolute
+cd $top_srcdir; top_srcdir=`pwd`
+
+export STAT_CONFIG_PATH=$top_srcdir/config
+
+
+cleanup()
+{
+     rm -rf $TEMPDIR
+}
+
+
+fail()
+{
+    echo $activity
+    echo FAILED
+    cleanup;
+    exit 1;
+}
+
+
+no_result()
+{
+    echo $activity
+    echo NO RESULT;
+    cleanup;
+    exit 2;
+}
+
+pass()
+{
+    cleanup;
+    exit 0;
+}
+
+mkdir -p $TEMPDIR
+
+cd $TEMPDIR
+
+activity="create program 1"
+cat > $TEMPDIR/out.stat <<EOF
+data list list /id * a * b * c * d *.
+begin data.
+1 2.0 3.0 4.0 4.0
+2 1.0 2.0 5.1 3.9
+3 2.0 4.5 5.2 3.8
+4 2.0 4.5 5.3 3.7
+56 3.0 6.0 5.9 3.6
+end data.
+
+t-test /PAIRS a c with b d (PAIRED). 
+EOF
+if [ $? -ne 0 ] ; then no_result ; fi
+
+
+activity="run program 1"
+$here/../src/pspp -o raw-ascii $TEMPDIR/out.stat
+if [ $? -ne 0 ] ; then no_result ; fi
+
+activity="copy output"
+mv $TEMPDIR/pspp.list $TEMPDIR/ref.list
+if [ $? -ne 0 ] ; then no_result ; fi
+
+activity="create program 2"
+cat > $TEMPDIR/out.stat <<EOF
+data list list /id * a * b * c * d *.
+begin data.
+1 2.0 3.0 4.0 4.0 
+2 1.0 2.0 5.1 3.9
+3 2.0 4.5 5.2 3.8
+4 2.0 4.5 5.3 3.7
+5 3.0 6.0 5.9 .
+6 3.0  .  5.9 3.6
+end data.
+
+
+t-test /MISSING=analysis /PAIRS a c with b d (PAIRED). 
+EOF
+if [ $? -ne 0 ] ; then no_result ; fi
+
+
+activity="run program 2"
+$here/../src/pspp -o raw-ascii $TEMPDIR/out.stat
+if [ $? -ne 0 ] ; then no_result ; fi
+
+
+activity="compare outputs"
+diff $TEMPDIR/ref.list $TEMPDIR/pspp.list
+if [ $? -ne 0 ] ; then fail ; fi
+
+
+pass
diff --git a/tests/command/t-test-paired-missing-list.sh b/tests/command/t-test-paired-missing-list.sh
new file mode 100755 (executable)
index 0000000..21dbc37
--- /dev/null
@@ -0,0 +1,101 @@
+#!/bin/sh
+
+# This program tests that the T-TEST /PAIRS command works OK
+# when there is listwise missing data involved.
+
+TEMPDIR=/tmp/pspp-tst-$$
+
+here=`pwd`;
+
+# ensure that top_srcdir is absolute
+cd $top_srcdir; top_srcdir=`pwd`
+
+export STAT_CONFIG_PATH=$top_srcdir/config
+
+
+cleanup()
+{
+     rm -rf $TEMPDIR
+}
+
+
+fail()
+{
+    echo $activity
+    echo FAILED
+    cleanup;
+    exit 1;
+}
+
+
+no_result()
+{
+    echo $activity
+    echo NO RESULT;
+    cleanup;
+    exit 2;
+}
+
+pass()
+{
+    cleanup;
+    exit 0;
+}
+
+mkdir -p $TEMPDIR
+
+cd $TEMPDIR
+
+activity="create program 1"
+cat > $TEMPDIR/out.stat <<EOF
+data list list /id * a * b * c * d *.
+begin data.
+1 2.0 3.0 4.0 4.0
+2 1.0 2.0 5.1 3.9
+3 2.0 4.5 5.2 3.8
+4 2.0 4.5 5.3 3.7
+5 3.0 6.0 5.9 3.6
+end data.
+
+t-test /PAIRS a b with c d (PAIRED). 
+EOF
+if [ $? -ne 0 ] ; then no_result ; fi
+
+
+activity="run program 1"
+$here/../src/pspp -o raw-ascii $TEMPDIR/out.stat
+if [ $? -ne 0 ] ; then no_result ; fi
+
+activity="copy output"
+mv $TEMPDIR/pspp.list $TEMPDIR/ref.list
+if [ $? -ne 0 ] ; then no_result ; fi
+
+activity="create program 2"
+cat > $TEMPDIR/out.stat <<EOF
+data list list /id * a * b * c * d *.
+begin data.
+1 2.0 3.0 4.0 4.0 
+2 1.0 2.0 5.1 3.9
+3 2.0 4.5 5.2 3.8
+4 2.0 4.5 5.3 3.7
+5 3.0 6.0 5.9 3.6
+6 3.0 6.0 5.9  .
+end data.
+
+
+t-test /MISSING=listwise /PAIRS a b with c d (PAIRED). 
+EOF
+if [ $? -ne 0 ] ; then no_result ; fi
+
+
+activity="run program 2"
+$here/../src/pspp -o raw-ascii $TEMPDIR/out.stat
+if [ $? -ne 0 ] ; then no_result ; fi
+
+
+activity="compare outputs"
+diff $TEMPDIR/ref.list $TEMPDIR/pspp.list
+if [ $? -ne 0 ] ; then fail ; fi
+
+
+pass