FACTOR: Fix bug interpreting the /CRITERIA=ITERATE subcommand 20130917030502/pspp 20130918030502/pspp 20130919030506/pspp
authorJohn Darrington <john@darrington.wattle.id.au>
Mon, 16 Sep 2013 06:49:43 +0000 (08:49 +0200)
committerJohn Darrington <john@darrington.wattle.id.au>
Mon, 16 Sep 2013 16:00:39 +0000 (18:00 +0200)
doc/statistics.texi
src/language/stats/factor.c
tests/language/stats/factor.at

index 0f1c886f1b2eb70eaca03b7edc1de6e298ad948d..03e4a44e4c387f25196b6da63b187c3a9570d7d4 100644 (file)
@@ -705,13 +705,23 @@ performed, and all coefficients will be printed.
 The @subcmd{/CRITERIA} subcommand is used to specify how the number of extracted factors (components) are chosen.
 If @subcmd{FACTORS(@var{n})} is
 specified, where @var{n} is an integer, then @var{n} factors will be extracted.  Otherwise, the @subcmd{MINEIGEN} setting will
-be used.  @subcmd{MINEIGEN(@var{l})} requests that all factors whose eigenvalues are greater than or equal to @var{l} are extracted.
-The default value of @var{l} is 1.    The @subcmd{ECONVERGE} and @subcmd{ITERATE} settings have effect only when iterative algorithms for factor
-extraction (such as Principal Axis Factoring) are used.   @subcmd{ECONVERGE(@var{delta})} specifies that
+be used.  
+@subcmd{MINEIGEN(@var{l})} requests that all factors whose eigenvalues are greater than or equal to @var{l} are extracted.
+The default value of @var{l} is 1.    
+The @subcmd{ECONVERGE} setting has effect only when iterative algorithms for factor
+extraction (such as Principal Axis Factoring) are used.   
+@subcmd{ECONVERGE(@var{delta})} specifies that
 iteration should cease when
 the maximum absolute value of the communality estimate between one iteration and the previous is less than @var{delta}. The
 default value of @var{delta} is 0.001.
-The @subcmd{ITERATE(@var{m})} setting sets the maximum number of iterations to @var{m}.  The default value of @var{m} is 25.
+The @subcmd{ITERATE(@var{m})} may appear any number of times and is used for two different purposes.  
+It is used to set the maximum number of iterations (@var{m}) for convergence and also to set the maximum number of iterations
+for rotation.
+Whether it affects convergence or rotation depends upon which subcommand follows the @subcmd{ITERATE} subcommand.
+If @subcmd{EXTRACTION} follows, it affects convergence.  
+If @subcmd{ROTATION} follows, it affects rotation.  
+If neither @subcmd{ROTATION} nor @subcmd{EXTRACTION} follow a @subcmd{ITERATE} subcommand it will be ignored.
+The default value of @var{m} is 25.
 
 The @cmd{MISSING} subcommand determines the handling of missing variables.  
 If @subcmd{INCLUDE} is set, then user-missing values are included in the
index f3933268431c646e70ed741fd74b7856567ab011..fa9987332fb93bdbdfad55a6f3b58e2750e114a6 100644 (file)
@@ -152,12 +152,13 @@ struct cmd_factor
   enum extraction_method extraction;
   enum plot_opts plot;
   enum rotation_type rotation;
+  int rotation_iterations;
 
   /* Extraction Criteria */
   int n_factors;
   double min_eigen;
   double econverge;
-  int iterations;
+  int extraction_iterations;
 
   double rconverge;
 
@@ -658,7 +659,7 @@ rotate (const struct cmd_factor *cf, const gsl_matrix *unrot,
   /* Now perform the rotation iterations */
 
   prev_sv = initial_sv (normalised);
-  for (i = 0 ; i < cf->iterations ; ++i)
+  for (i = 0 ; i < cf->rotation_iterations ; ++i)
     {
       double sv = 0.0;
       for (j = 0 ; j < normalised->size2; ++j)
@@ -814,7 +815,7 @@ int
 cmd_factor (struct lexer *lexer, struct dataset *ds)
 {
   const struct dictionary *dict = dataset_dict (ds);
-
+  int n_iterations = 25;
   struct cmd_factor factor;
   factor.n_vars = 0;
   factor.vars = NULL;
@@ -825,7 +826,8 @@ cmd_factor (struct lexer *lexer, struct dataset *ds)
   factor.extraction = EXTRACTION_PC;
   factor.n_factors = 0;
   factor.min_eigen = SYSMIS;
-  factor.iterations = 25;
+  factor.extraction_iterations = 25;
+  factor.rotation_iterations = 25;
   factor.econverge = 0.001;
 
   factor.blank = 0;
@@ -926,6 +928,7 @@ cmd_factor (struct lexer *lexer, struct dataset *ds)
                  goto error;
                }
            }
+          factor.rotation_iterations = n_iterations;
        }
       else if (lex_match_id (lexer, "CRITERIA"))
        {
@@ -977,7 +980,7 @@ cmd_factor (struct lexer *lexer, struct dataset *ds)
                  if ( lex_force_match (lexer, T_LPAREN))
                    {
                      lex_force_int (lexer);
-                     factor.iterations = lex_integer (lexer);
+                     n_iterations = lex_integer (lexer);
                      lex_get (lexer);
                      lex_force_match (lexer, T_RPAREN);
                    }
@@ -986,7 +989,7 @@ cmd_factor (struct lexer *lexer, struct dataset *ds)
                {
                  factor.n_factors = 0;
                  factor.min_eigen = 1;
-                 factor.iterations = 25;
+                 n_iterations = 25;
                }
              else
                {
@@ -1022,6 +1025,7 @@ cmd_factor (struct lexer *lexer, struct dataset *ds)
                  goto error;
                }
            }
+          factor.extraction_iterations = n_iterations;
        }
       else if (lex_match_id (lexer, "FORMAT"))
        {
@@ -1955,7 +1959,7 @@ do_factor (const struct cmd_factor *factor, struct casereader *r)
 
        gsl_vector_memcpy (initial_communalities, idata->msr);
 
-       for (i = 0; i < factor->iterations; ++i)
+       for (i = 0; i < factor->extraction_iterations; ++i)
          {
            double min, max;
            gsl_vector_memcpy (diff, idata->msr);
index b26af0a7c9123f6b30c40cc08bda374271605977..d40cd28e92c556159fdeded3730f4d310631620c 100644 (file)
@@ -1868,3 +1868,56 @@ TRAIT4,.97,.21,-.04,.00
 TRAIT5,.70,-.67,-.23,.00
 ])
 AT_CLEANUP
+
+
+
+dnl Fixes a bug in the way that the /CRITERIA = ITERATE option was interpreted.
+dnl http://lists.gnu.org/archive/html/bug-gnu-pspp/2013-09/msg00036.html
+AT_SETUP([FACTOR /CRITERIA=ITERATE])
+AT_DATA([factor-iterate.sps], [dnl
+set format = F20.3.
+data list notable list /x y z *.
+begin data.
+1.00    5.00    3.00
+2.00    2.00    2.00
+3.00    1.00    1.00
+4.00    4.00    5.00
+5.00    3.00    9.00
+6.00    6.00    4.00
+7.00    7.00    6.00
+8.00    8.00    8.00
+9.00    9.00    7.00
+end data.
+
+FACTOR
+ /VARIABLES= x y z
+ /CRITERIA = MINEIGEN (1) ITERATE (25)
+ /EXTRACTION =PAF
+ /METHOD = CORRELATION
+ /PRINT = INITIAL EXTRACTION
+ /CRITERIA = ITERATE (0)
+ /ROTATION = NOROTATE.
+])
+
+AT_CHECK([pspp -O format=csv factor-iterate.sps], [0], [dnl
+Table: Communalities
+,Initial,Extraction
+x,.735,.979
+y,.640,.653
+z,.514,.523
+
+Table: Total Variance Explained
+,Initial Eigenvalues,,,Extraction Sums of Squared Loadings,,
+Factor,Total,% of Variance,Cumulative %,Total,% of Variance,Cumulative %
+1,2.404,80.124,80.124,2.155,71.847,71.847
+2,.425,14.166,94.290,,,
+3,.171,5.710,100.000,,,
+
+Table: Factor Matrix
+,Factor
+,1
+x,.990
+y,.808
+z,.723
+])
+AT_CLEANUP
\ No newline at end of file