source: src/main/java/agents/anac/y2015/agentBuyogV2/flanagan/analysis/PCA.java

Last change on this file was 127, checked in by Wouter Pasman, 6 years ago

#41 ROLL BACK of rev.126 . So this version is equal to rev. 125

File size: 78.3 KB
Line 
1/*
2* CLASS: PCA
3*
4* USAGE: Principlal Component Analysis
5*
6* This is a subclass of the superclass Scores
7*
8*
9* WRITTEN BY: Dr Michael Thomas Flanagan
10*
11* DATE: October 2008
12* AMENDED: 17-18 October 2008, 4 January 2010, 13 November 2010, 29-30 November 2010, 4 December 2010, 18 January 2011
13*
14* DOCUMENTATION:
15* See Michael Thomas Flanagan's Java library on-line web pages:
16* http://www.ee.ucl.ac.uk/~mflanaga/java/
17* http://www.ee.ucl.ac.uk/~mflanaga/java/PCA.html
18*
19* Copyright (c) 2008 - 2011 Michael Thomas Flanagan
20*
21* PERMISSION TO COPY:
22*
23* Permission to use, copy and modify this software and its documentation for NON-COMMERCIAL purposes is granted, without fee,
24* provided that an acknowledgement to the author, Dr Michael Thomas Flanagan at www.ee.ucl.ac.uk/~mflanaga, appears in all copies
25* and associated documentation or publications.
26*
27* Redistributions of the source code of this source code, or parts of the source codes, must retain the above copyright notice, this list of conditions
28* and the following disclaimer and requires written permission from the Michael Thomas Flanagan:
29*
30* Redistribution in binary form of all or parts of this class must reproduce the above copyright notice, this list of conditions and
31* the following disclaimer in the documentation and/or other materials provided with the distribution and requires written permission from the Michael Thomas Flanagan:
32*
33* Dr Michael Thomas Flanagan makes no representations about the suitability or fitness of the software for any or for a particular purpose.
34* Dr Michael Thomas Flanagan shall not be liable for any damages suffered as a result of using, modifying or distributing this software
35* or its derivatives.
36*
37***************************************************************************************/
38
39
40package agents.anac.y2015.agentBuyogV2.flanagan.analysis;
41
42import java.util.*;
43
44import agents.anac.y2015.agentBuyogV2.flanagan.analysis.*;
45import agents.anac.y2015.agentBuyogV2.flanagan.io.*;
46import agents.anac.y2015.agentBuyogV2.flanagan.math.*;
47import agents.anac.y2015.agentBuyogV2.flanagan.plot.*;
48
49import java.text.*;
50import java.awt.*;
51
52
53public class PCA extends Scores{
54
55 private Matrix data = null; // data as row per item as a Matrix
56 private Matrix dataMinusMeans = null; // data with row means subtracted as row per item as a Matrix
57 private Matrix dataMinusMeansTranspose = null; // data with row means subtracted as row per item as a Matrix
58 private Matrix covarianceMatrix = null; // variance-covariance Matrix
59 private Matrix correlationMatrix = null; // variance-covariance Matrix
60
61 private double[] eigenValues = null; // eigenvalues
62 private double[] orderedEigenValues = null; // eigenvalues sorted into a descending order
63 private int[] eigenValueIndices = null; // indices of the eigenvalues before sorting into a descending order
64 private double eigenValueTotal = 0.0; // total of all eigen values;
65 private int[] rotatedIndices = null; // rearranged indices on ordering after rotation
66
67 private double[] rotatedEigenValues = null; // scaled rotated eigenvalues
68 private double[] usRotatedEigenValues = null; // unscaled rotated eigenvalues
69
70
71 private int nMonteCarlo = 200; // number of Monte Carlo generated eigenvalue calculations
72 private double[][] randomEigenValues = null; // Monte Carlo generated eigenvalues
73 private double[] randomEigenValuesMeans = null; // means of the Monte Carlo generated eigenvalues
74 private double[] randomEigenValuesSDs = null; // standard deviations of the Monte Carlo generated eigenvalues
75 private double[] randomEigenValuesPercentiles = null; // percentiles of the Monte Carlo generated eigenvalues
76 private double percentile = 95.0; // percentile used in parallel analysis
77 private boolean gaussianDeviates = false; // = false: uniform random deviates used in Monte Carlo
78 // = true: Gaussian random deviates used in Monte Carlo
79 private double[] proportionPercentage = null; // eigenvalues expressesed as percentage of total
80 private double[] cumulativePercentage = null; // cumulative values of the eigenvalues expressesed as percentage of total
81 private double[] rotatedProportionPercentage = null; // scaled rotated eigenvalues expressesed as percentage of unrotated total
82 private double[] rotatedCumulativePercentage = null; // scaled rotated cumulative values of the eigenvalues expressesed as percentage of unrotated total
83
84 private double[][] eigenVectorsAsColumns = null; // eigenvectors as columns
85 private double[][] eigenVectorsAsRows = null; // eigenvectors as rows
86
87 private double[][] orderedEigenVectorsAsColumns = null; // eigenvectors, as columns, arranged to match a descending order of eigenvalues
88 private double[][] orderedEigenVectorsAsRows = null; // eigenvectors, as rows, arranged to match a descending order of eigenvalues
89
90 private double[][] loadingFactorsAsColumns = null; // loading factors as column per eigenvalue
91 private double[][] loadingFactorsAsRows = null; // loading factors as row per eigenvalue
92
93 private double[][] rotatedLoadingFactorsAsColumns = null; // scaled rotated loading factors as column per eigenvalue
94 private double[][] rotatedLoadingFactorsAsRows = null; // scaled rotated loading factors as row per eigenvalue
95 private double[][] usRotatedLoadingFactorsAsColumns = null; // unscaled rotated loading factors as column per eigenvalue
96 private double[][] usRotatedLoadingFactorsAsRows = null; // unscaled rotated loading factors as row per eigenvalue
97
98 private double[] communalities = null; // communalities
99 private double[] communalityWeights = null; // communality weights
100
101 private boolean covRhoOption = false; // = true: covariance matrix used
102 // = false: correlation matrix used
103
104 private int greaterThanOneLimit = 0; // number of components extracted using eigenvalue greater than one
105 private int percentileCrossover = 0; // number of components extracted using percentile scree crossover
106 private int meanCrossover = 0; // number of components extracted using mean scree crossover
107
108 private int nVarimaxMax = 1000; // maximum iterations allowed by the varimax criterion
109 private int nVarimax = 0; // number of iterations taken by the varimax criterion
110 private double varimaxTolerance = 1.0E-8; // tolerance for terminatiing 2 criterion iteration
111
112 private boolean varimaxOption = true; // = true: normal varimax, i.e. comunality weighted varimax
113 // = false: raw varimax
114 private boolean pcaDone = false; // = true when PCA performed
115 private boolean monteCarloDone = false; // = true when parallel monte Carlo simultaion performed
116 private boolean rotationDone = false; // = true when rotation performed
117
118
119
120 // CONSTRUCTOR
121 public PCA(){
122 super.trunc = 4;
123 }
124
125 // CHOICE OF MATRIX
126 // Use covariance matrix (default option)
127 public void useCovarianceMatrix(){
128 this.covRhoOption = true;
129 }
130
131 // Use correlation matrix (default option)
132 public void useCorrelationMatrix(){
133 this.covRhoOption = false;
134 }
135
136 // CHOICE OF VARIMAX CRITERION
137 // Use normal varimax rotation
138 public void useNormalVarimax(){
139 this. varimaxOption = true;
140 }
141
142 // Use raw varimax rotation
143 public void useRawVarimax(){
144 this. varimaxOption = false;
145 }
146
147 // Return varimax rotation option
148 public String getVarimaxOption(){
149 if(this. varimaxOption){
150 return "normal varimax option";
151 }
152 else{
153 return "raw varimax option";
154 }
155 }
156
157 // PARALLEL ANALYSIS OPTIONS
158 // Reset number of Monte Carlo simulations
159 public void setNumberOfSimulations(int nSimul){
160 this.nMonteCarlo = nSimul;
161 }
162
163 // Return number of Monte Carlo simulations
164 public int getNumberOfSimulations(){
165 return this.nMonteCarlo;
166 }
167
168 // Use Gaussian random deviates in MontMonte Carlo simulations
169 public void useGaussianDeviates(){
170 this.gaussianDeviates = true;
171 }
172
173 // Use uniform random deviates in MontMonte Carlo simulations
174 public void useUniformDeviates(){
175 this.gaussianDeviates = false;
176 }
177
178 // Reset percentile percentage in parallel analysis (defalut option = 95%)
179 public void setParallelAnalysisPercentileValue(double percent){
180 this.percentile = percent;
181 }
182
183 // Return percentile percentage in parallel analysis (defalut option = 95%)
184 public double getParallelAnalysisPercentileValue(){
185 return this.percentile;
186 }
187
188
189
190 // PRINCIPAL COMPONENT ANALYSIS
191 public void pca(){
192
193 if(!this.pcaDone){
194
195 if(this.nItems==1)throw new IllegalArgumentException("You have entered only one item - PCA is not meaningful");
196 if(this.nPersons==1)throw new IllegalArgumentException("You have entered only one score or measurement source - PCA is not meaningful");
197
198 // Check that data is preprocessed
199 if(!this.dataPreprocessed)this.preprocessData();
200
201 // Store data as an instance of matrix
202 this.data = new Matrix(super.scores0);
203
204 // Subtract row means
205 this.dataMinusMeans = this.data.subtractRowMeans();
206
207 // Transpose
208 this.dataMinusMeansTranspose = this.dataMinusMeans.transpose();
209
210 // Covariance matrix
211 this.covarianceMatrix = this.dataMinusMeans.times(this.dataMinusMeansTranspose);
212 double denom = this.nPersons;
213 if(!super.nFactorOption)denom -= 1.0;
214 this.covarianceMatrix = this.covarianceMatrix.times(1.0/denom);
215
216
217
218 // Correlation matrix
219 boolean tinyCheck = false;
220 double[][] cov = this.covarianceMatrix.getArrayCopy();
221 double[][] corr = new double[this.nItems][this.nItems];
222 for(int i=0; i<this.nItems; i++){
223 for(int j=0; j<this.nItems; j++){
224 if(i==j){
225 corr[i][j] = 1.0;
226 }
227 else{
228 corr[i][j] = cov[i][j]/Math.sqrt(cov[i][i]*cov[j][j]);
229 if(Fmath.isNaN(corr[i][j])){
230 corr[i][j] = 0.0;
231 }
232 }
233 }
234 }
235
236 this.correlationMatrix = new Matrix(corr);
237
238 // Choose matrix
239 Matrix forEigen = null;
240 if(covRhoOption){
241 forEigen = this.covarianceMatrix;
242 }
243 else{
244 forEigen = this.correlationMatrix;
245 }
246
247 // Calculate eigenvalues
248 this.eigenValues = forEigen.getEigenValues();
249
250 // Calculate ordered eigenvalues
251 this.orderedEigenValues = forEigen.getSortedEigenValues();
252
253 // Store indices of the eigenvalues before sorting into escending order
254 this.eigenValueIndices = forEigen.eigenValueIndices();
255
256 // Calculate eigenvectors
257 this.eigenVectorsAsColumns = forEigen.getEigenVectorsAsColumns();
258 this.eigenVectorsAsRows = forEigen.getEigenVectorsAsRows();
259
260 // Calculate ordered eigenvectors
261 this.orderedEigenVectorsAsColumns = forEigen.getSortedEigenVectorsAsColumns();
262 this.orderedEigenVectorsAsRows = forEigen.getSortedEigenVectorsAsRows();
263
264 // Express eigenvalues as percentage of total
265 ArrayMaths am = new ArrayMaths(this.orderedEigenValues);
266 double total = am.sum();
267 am = am.times(100.0/total);
268 this.proportionPercentage = am.array();
269
270 // Calculate cumulative percentage
271 this.cumulativePercentage = new double[this.nItems];
272 this.cumulativePercentage[0] = this.proportionPercentage[0];
273 this.eigenValueTotal = 0.0;
274 for(int i=1; i<this.nItems; i++){
275 this.cumulativePercentage[i] = this.cumulativePercentage[i-1] + this.proportionPercentage[i];
276 this.eigenValueTotal += this.eigenValues[i];
277 }
278
279
280 // Calculate 'eigenvalue less than or equal to one' extraction limit
281 boolean test = true;
282 int counter = 0;
283 while(test){
284 if(this.orderedEigenValues[counter]<1.0){
285 this.greaterThanOneLimit = counter;
286 test = false;
287 }
288 else{
289 counter++;
290 if(counter==this.nItems){
291 this.greaterThanOneLimit = counter;
292 test = false;
293 }
294 }
295 }
296
297 // Calculate loading factors
298 this.loadingFactorsAsColumns = new double[this.nItems][this.nItems];
299 this.loadingFactorsAsRows = new double[this.nItems][this.nItems];
300 for(int i=0; i<this.nItems; i++){
301 for(int j=0; j<this.nItems; j++){
302 this.loadingFactorsAsColumns[i][j] = this.orderedEigenVectorsAsColumns[i][j]*Math.sqrt(Math.abs(this.orderedEigenValues[j]));
303 this.loadingFactorsAsRows[i][j] = this.orderedEigenVectorsAsRows[i][j]*Math.sqrt(Math.abs(this.orderedEigenValues[i]));
304 }
305 }
306
307 // Calculate communalities
308 this.communalities = new double[this.nItems];
309 this.communalityWeights = new double[this.nItems];
310 for(int k=0; k<this.nItems; k++){
311 double sum = 0.0;
312 for(int j=0; j<this.nItems; j++)sum += loadingFactorsAsRows[j][k]*loadingFactorsAsRows[j][k];
313 this.communalities[k] = sum;
314 this.communalityWeights[k] = Math.sqrt(this.communalities[k]);
315 }
316
317 }
318
319 this.pcaDone = true;
320
321 }
322
323 // MonteCarlo Eigenvalues
324 public void monteCarlo(){
325 if(!pcaDone)this.pca();
326 double[] rowMeans = super.rawItemMeans();
327 double[] rowSDs = super.rawItemStandardDeviations();
328 double[][] randomData = new double[super.nItems][super.nPersons];
329 this.randomEigenValues = new double[this.nMonteCarlo][super.nItems];
330 PsRandom rr = new PsRandom();
331 for(int i=0; i<this.nMonteCarlo; i++){
332 for(int j=0; j<this.nItems; j++){
333 if(this.gaussianDeviates){
334 randomData[j] = rr.gaussianArray(rowMeans[j], rowSDs[j], super.nPersons);
335 }
336 else{
337 randomData[j] = rr.doubleArray(super.nPersons);
338 randomData[j] = Stat.scale(randomData[j], rowMeans[j], rowSDs[j]);
339 }
340 }
341 PCA pca = new PCA();
342 if(this.covRhoOption){
343 pca.useCovarianceMatrix();
344 }
345 else{
346 pca.useCorrelationMatrix();
347 }
348 pca.enterScoresAsRowPerItem(randomData);
349 this.randomEigenValues[i] = pca.orderedEigenValues();
350
351 }
352 Matrix mat = new Matrix(randomEigenValues);
353 this.randomEigenValuesMeans = mat.columnMeans();
354 this.randomEigenValuesSDs = mat.columnStandardDeviations();
355 this.randomEigenValuesPercentiles = new double[this.nItems];
356
357 int pIndex1 = (int)Math.ceil(this.nMonteCarlo*this.percentile/100.0);
358 int pIndex2 = pIndex1-1;
359 double factor = (this.percentile*this.nMonteCarlo/100.0 - pIndex2);
360 pIndex1--;
361 pIndex2--;
362 for(int j=0; j<this.nItems; j++){
363 double[] ordered = new double[this.nMonteCarlo];
364 for(int k=0; k<this.nMonteCarlo; k++)ordered[k] = this.randomEigenValues[k][j];
365 ArrayMaths am = new ArrayMaths(ordered);
366 am = am.sort();
367 ordered = am.array();
368 this.randomEigenValuesPercentiles[j] = ordered[pIndex2] + factor*(ordered[pIndex1] - ordered[pIndex2]);
369 }
370
371 // Calculate percentile crossover extraction limit
372 boolean test = true;
373 int counter = 0;
374 while(test){
375 if(this.orderedEigenValues[counter]<=this.randomEigenValuesPercentiles[counter]){
376 this.percentileCrossover = counter;
377 test = false;
378 }
379 else{
380 counter++;
381 if(counter==this.nItems){
382 this.percentileCrossover = counter;
383 test = false;
384 }
385 }
386 }
387
388 // Calculate mean crossover extraction limit
389 test = true;
390 counter = 0;
391 while(test){
392 if(this.orderedEigenValues[counter]<=this.randomEigenValuesMeans[counter]){
393 this.meanCrossover = counter;
394 test = false;
395 }
396 else{
397 counter++;
398 if(counter==this.nItems){
399 this.meanCrossover = counter;
400 test = false;
401 }
402 }
403 }
404
405 this.monteCarloDone = true;
406
407 }
408
409 // SCREE PLOTS
410 // Scree plot of data alone
411 public void screePlotDataAlone(){
412 if(!this.pcaDone)this.pca();
413
414 // Create X-axis data array
415 double[] components = new double[super.nItems];
416 for(int i=0; i<this.nItems; i++)components[i] = i+1;
417
418 // Create instance of PlotGraph
419 PlotGraph pg = new PlotGraph(components, this.orderedEigenValues);
420 pg.setGraphTitle("Principal Component Analysis Scree Plot");
421 pg.setXaxisLegend("Component");
422 pg.setYaxisLegend("Eigenvalues");
423 pg.setLine(3);
424 pg.setPoint(1);
425 pg.plot();
426 }
427
428
429 // Scree plot eigenvalues plus plot of Monte Carlo percentiles, means and standard deviations
430 public void screePlot(){
431 if(!this.pcaDone)this.pca();
432 if(!this.monteCarloDone)this.monteCarlo();
433
434 // Create plotting data array
435 double[][] plotData = new double[6][super.nItems];
436 double[] components = new double[super.nItems];
437 for(int i=0; i<this.nItems; i++)components[i] = i+1;
438 plotData[0] = components;
439 plotData[1] = this.orderedEigenValues;
440 plotData[2] = components;
441 plotData[3] = this.randomEigenValuesPercentiles;
442 plotData[4] = components;
443 plotData[5] = this.randomEigenValuesMeans;
444
445 // Create instance of PlotGraph
446 PlotGraph pg = new PlotGraph(plotData);
447 pg.setErrorBars(2, this.randomEigenValuesSDs);
448 if(this.gaussianDeviates){
449 pg.setGraphTitle("Principal Component Analysis Scree Plot with Parallel Analysis using Gaussian deviates (" + nMonteCarlo + " simulations)");
450 }
451 else{
452 pg.setGraphTitle("Principal Component Analysis Scree Plot with Parallel Analysis using uniform deviates (" + nMonteCarlo + " simulations)");
453 }
454 pg.setGraphTitle2("Closed squares - data eigenvalues; open circles = Monte Carlo eigenvalue " + this.percentile + "% percentiles; error bars = standard deviations about the Monte carlo means (crosses)");
455 pg.setXaxisLegend("Component");
456 pg.setYaxisLegend("Eigenvalue");
457 int[] line = {3, 0, 3};
458 pg.setLine(line);
459 int point[] = {5, 1, 7};
460 pg.setPoint(point);
461 pg.plot();
462 }
463
464
465 // VARIMAX ROTATION
466 // Set varimax tolerance
467 public void setVarimaxTolerance(double tolerance){
468 this.varimaxTolerance = tolerance;
469 }
470
471 // Set varimax maximum number of iterations
472 public void setVarimaxMaximumIterations(int max){
473 this.nVarimaxMax = max;
474 }
475
476 // Get varimax number of iterations
477 public int getVarimaxIterations(){
478 return this.nVarimax;
479 }
480
481
482 // Varimax rotation: option set by default
483 public void varimaxRotation(int nFactors){
484 if(!this.pcaDone)this.pca();
485 if(this.varimaxOption){
486 this.normalVarimaxRotation(nFactors);
487 }
488 else{
489 this.rawVarimaxRotation(nFactors);
490 }
491 }
492
493 // Varimax rotation: option set by default
494 // only raw option possible
495 public void varimaxRotation(double[][] loadingFactorMatrix){
496 if(this.varimaxOption)System.out.println("Method varimaxRotation: communality weights not supplied - raw varimax option used");
497 this.rawVarimaxRotationInHouse(loadingFactorMatrix);
498 }
499
500 // Varimax rotation: option set by default
501 public void varimaxRotation(double[][] loadingFactorMatrix, double[] communalityWeights){
502 if(this.varimaxOption){
503 this.normalVarimaxRotationInHouse(loadingFactorMatrix, communalityWeights);
504 }
505 else{
506 System.out.println("Method varimaxRotation: raw varimax option chosen, supplied communality weights ignored");
507 this.rawVarimaxRotationInHouse(loadingFactorMatrix);
508 }
509 }
510
511
512 // Raw varimax rotation
513 public void rawVarimaxRotation(int nFactors){
514 if(!this.pcaDone)this.pca();
515 double[][] loadingFactorMatrix = new double[nFactors][this.nItems];
516 for(int i = 0; i<nFactors; i++)loadingFactorMatrix[i] = this.loadingFactorsAsRows[i];
517 double[] communalityWeights = new double[this.nItems];
518 for(int i = 0; i<this.nItems; i++)communalityWeights[i] = 1.0;
519 this.normalVarimaxRotationInHouse(loadingFactorMatrix, communalityWeights);
520 }
521
522 // Raw varimax rotation
523 private void rawVarimaxRotationInHouse(double[][] loadingFactorMatrix){
524 double[] communalityWeights = new double[this.nItems];
525 for(int i = 0; i<this.nItems; i++)communalityWeights[i] = 1.0;
526 this.normalVarimaxRotationInHouse(loadingFactorMatrix, communalityWeights);
527 }
528
529 // Normal varimax rotation
530 public void normalVarimaxRotation(int nFactors){
531 if(!this.pcaDone)this.pca();
532 double[][] loadingFactorMatrix = new double[nFactors][this.nItems];
533 for(int i = 0; i<nFactors; i++)loadingFactorMatrix[i] = this.loadingFactorsAsRows[i];
534 double[] communalityWeights = new double[this.nItems];
535 for(int i = 0; i<nItems; i++){
536 communalityWeights[i] = 0.0;
537 for(int j = 0; j<nFactors; j++)communalityWeights[i] += loadingFactorMatrix[j][i]*loadingFactorMatrix[j][i];
538 }
539 this.normalVarimaxRotationInHouse(loadingFactorMatrix, communalityWeights);
540 }
541
542 // Normal varimax rotation - also used by raw varimax rotation with weights set to unity
543 private void normalVarimaxRotationInHouse(double[][] loadingFactorMatrix, double[] communalityWeights){
544 if(!this.pcaDone)this.pca();
545 int nRows = loadingFactorMatrix.length;
546 int nColumns = loadingFactorMatrix[0].length;
547 this.usRotatedLoadingFactorsAsRows = new double[nRows][nColumns];
548 this.rotatedLoadingFactorsAsRows = new double[nRows][nColumns];
549 this.usRotatedEigenValues = new double[nRows];
550 this.rotatedEigenValues = new double[nRows];
551 this.rotatedProportionPercentage= new double[nRows];
552 this.rotatedCumulativePercentage= new double[nRows];
553
554 // Calculate weights and normalize the loading factors
555 for(int j = 0; j<nColumns; j++)communalityWeights[j] = Math.sqrt(communalityWeights[j]);
556 for(int i = 0; i<nRows; i++){
557 for(int j = 0; j<nColumns; j++){
558 if(loadingFactorMatrix[i][j]==0.0 && communalityWeights[j]==0){
559 loadingFactorMatrix[i][j] = 1.0;
560 }
561 else{
562 loadingFactorMatrix[i][j] /= communalityWeights[j];
563 }
564 this.usRotatedLoadingFactorsAsRows[i][j] = loadingFactorMatrix[i][j];
565 }
566 }
567
568 // Loop through pairwise rotations until varimax function maximised
569 double va = PCA.varimaxCriterion(this.usRotatedLoadingFactorsAsRows);
570 double vaLast = 0;
571 double angle = 0;
572 boolean test = true;
573 this.nVarimax = 0;
574 while(test){
575 for(int i=0; i<nRows-1; i++){
576 for(int j=i+1; j<nRows; j++){
577 angle = PCA.varimaxAngle(this.usRotatedLoadingFactorsAsRows, i, j);
578 this.usRotatedLoadingFactorsAsRows = PCA.singleRotation(this.usRotatedLoadingFactorsAsRows, i, j, angle);
579 va = PCA.varimaxCriterion(this.usRotatedLoadingFactorsAsRows);
580 }
581 }
582 if(Math.abs(va - vaLast)<this.varimaxTolerance){
583 test=false;
584 }
585 else{
586 vaLast = va;
587 this.nVarimax++;
588 if(this.nVarimax>nVarimaxMax){
589 test=false;
590 System.out.println("Method varimaxRotation: maximum iterations " + nVarimaxMax + " exceeded");
591 System.out.println("Tolerance = " + this.varimaxTolerance + ", Comparison value = " + Math.abs(va - vaLast));
592 System.out.println("Current values returned");
593 if(super.sameCheck>0){
594 System.out.println("Presence of identical element row/s and/or column/s in the data probably impeding convergence");
595 System.out.println("Returned values are likely to be correct");
596 }
597 }
598 }
599 }
600
601 // undo normalization of rotated loading factors
602 this.usRotatedLoadingFactorsAsColumns = new double[nColumns][nRows];
603 for(int i=0; i<nRows; i++){
604 for(int j=0; j<nColumns; j++){
605 this.usRotatedLoadingFactorsAsRows[i][j] *= communalityWeights[j];
606 this.usRotatedLoadingFactorsAsColumns[j][i] = this.usRotatedLoadingFactorsAsRows[i][j];
607 loadingFactorMatrix[i][j] *= communalityWeights[j];
608 }
609 }
610
611 // Rotated eigenvalues
612 double usRotatedEigenValueTotal = 0.0;
613 double unRotatedEigenValueTotal = 0.0;
614 for(int i=0; i<nRows; i++){
615 this.usRotatedEigenValues[i] = 0.0;
616 for(int j=0; j<nColumns; j++){
617 this.usRotatedEigenValues[i] += this.usRotatedLoadingFactorsAsRows[i][j]*this.usRotatedLoadingFactorsAsRows[i][j];
618 }
619 usRotatedEigenValueTotal += this.usRotatedEigenValues[i];
620 unRotatedEigenValueTotal += this.orderedEigenValues[i];
621 }
622
623 // Order unscaled rotated eigenvalues
624 ArrayMaths amrot = new ArrayMaths(this.usRotatedEigenValues);
625 amrot = amrot.sort();
626 this.usRotatedEigenValues = amrot.array();
627 int[] sortedRotIndices = amrot.originalIndices();
628
629 // reverse order
630 int nh = nRows/2;
631 double holdD = 0.0;
632 int holdI = 0;
633 for(int i=0; i<nh; i++){
634 holdD = this.usRotatedEigenValues[i];
635 this.usRotatedEigenValues[i] = this.usRotatedEigenValues[nRows - 1 - i];
636 this.usRotatedEigenValues[nRows - 1 - i] = holdD;
637 holdI = sortedRotIndices[i];
638 sortedRotIndices[i] = sortedRotIndices[nRows - 1 - i];
639 sortedRotIndices[nRows - 1 - i] = holdI;
640 }
641
642 // order rotated power factors to match ordered rotated eigenvalues
643 int nn = this.usRotatedLoadingFactorsAsRows.length;
644 int mm = this.usRotatedLoadingFactorsAsRows[0].length;
645 double[][] holdDA = new double[nn][mm];
646 for(int i=0; i<nn; i++){
647 for(int j=0; j<mm; j++){
648 holdDA[i][j] = this.usRotatedLoadingFactorsAsRows[sortedRotIndices[i]][j];
649 }
650 }
651 this.usRotatedLoadingFactorsAsRows = Conv.copy((double[][])holdDA);
652
653 nn = sortedRotIndices.length;
654 this.rotatedIndices = new int[nn];
655 int[]holdIA = new int[nn];
656 for(int i=0; i<nn; i++){
657 holdIA[i] = this.eigenValueIndices[sortedRotIndices[i]];
658 }
659 this.rotatedIndices = Conv.copy((int[])this.eigenValueIndices);
660 for(int i=0; i<nn; i++){
661 this.rotatedIndices[i] = holdIA[i];
662 }
663
664 // Scale rotated loading factors and eigenvalues to the unrotated variance percentage for the sum of the extracted eigenvalues
665 double scale0 = Math.abs(unRotatedEigenValueTotal/usRotatedEigenValueTotal);
666 double scale1 = Math.sqrt(scale0);
667 for(int i=0; i<nRows; i++){
668 this.rotatedEigenValues[i] = scale0*this.usRotatedEigenValues[i];
669 this.rotatedProportionPercentage[i] = this.rotatedEigenValues[i]*100.0/this.eigenValueTotal;
670 for(int j=0; j<nColumns; j++){
671 this.rotatedLoadingFactorsAsRows[i][j] = scale1*this.usRotatedLoadingFactorsAsRows[i][j];
672 }
673 }
674 this.rotatedCumulativePercentage[0] = this.rotatedProportionPercentage[0];
675 for(int i=1; i<nRows; i++)this.rotatedCumulativePercentage[i] = this.rotatedCumulativePercentage[i-1] + this.rotatedProportionPercentage[i];
676
677 this.rotationDone = true;
678
679 }
680
681 // Raw varimax rotation
682 // Static method - default tolerance and maximum iterations
683 public static double[][] rawVarimaxRotation(double[][] loadingFactorMatrix){
684 double tolerance = 0.0001;
685 int nIterMax = 1000;
686 return PCA.rawVarimaxRotation(loadingFactorMatrix, tolerance, nIterMax);
687 }
688
689 // Raw varimax rotation
690 // Static method - user supplied tolerance and maximum iterations
691 public static double[][] rawVarimaxRotation(double[][] loadingFactorMatrix, double tolerance, int nIterMax){
692 int nRows = loadingFactorMatrix.length;
693 int nColumns = loadingFactorMatrix[0].length;
694 double[] communalityWeights = new double[nColumns];
695 for(int i = 0; i<nColumns; i++){
696 communalityWeights[i] = 1.0;
697 }
698 return PCA.normalVarimaxRotation(loadingFactorMatrix, communalityWeights, tolerance, nIterMax);
699 }
700
701 // Normal varimax rotation - also used by raw varimax rotation with weights set to unity
702 // Static method - default tolerance and maximum iterations
703 public static double[][] normalVarimaxRotation(double[][] loadingFactorMatrix, double[] communalityWeights){
704 double tolerance = 0.0001;
705 int nIterMax = 1000;
706 return normalVarimaxRotation(loadingFactorMatrix, communalityWeights, tolerance, nIterMax);
707 }
708
709 // Normal varimax rotation - also used by raw varimax rotation with weights set to unity
710 // Static method - tolerance and maximum iterations provided by the user
711 public static double[][] normalVarimaxRotation(double[][] loadingFactorMatrix, double[] communalityWeights, double tolerance, int nIterMax){
712 int nRows = loadingFactorMatrix.length;
713 int nColumns = loadingFactorMatrix[0].length;
714 for(int i=1; i<nRows; i++)if(loadingFactorMatrix[i].length!=nColumns)throw new IllegalArgumentException("All rows must be the same length");
715 double[][] rotatedLoadingFactorsAsRows = new double[nRows][nColumns];
716
717 // Calculate weights and normalize the loading factors
718 for(int i = 0; i<nRows; i++){
719 for(int j = 0; j<nColumns; j++){
720 loadingFactorMatrix[i][j] /= communalityWeights[j];
721 rotatedLoadingFactorsAsRows[i][j] = loadingFactorMatrix[i][j];
722 }
723 }
724
725 // Loop through pairwise rotations until varimax function maximised
726 double va = PCA.varimaxCriterion(rotatedLoadingFactorsAsRows);
727 double vaLast = 0;
728 double angle = 0;
729 boolean test = true;
730 int nIter = 0;
731 while(test){
732 for(int i=0; i<nRows-1; i++){
733 for(int j=i+1; j<nRows; j++){
734 angle = PCA.varimaxAngle(rotatedLoadingFactorsAsRows, i, j);
735 rotatedLoadingFactorsAsRows = PCA.singleRotation(rotatedLoadingFactorsAsRows, i, j, angle);
736 va = PCA.varimaxCriterion(rotatedLoadingFactorsAsRows);
737 }
738 }
739 if(Math.abs(va - vaLast)<tolerance){
740 test=false;
741 }
742 else{
743 vaLast = va;
744 nIter++;
745 if(nIter>nIterMax){
746 test=false;
747 System.out.println("Method varimaxRotation: maximum iterations " + nIterMax + " exceeded");
748 System.out.println("Current values returned");
749 }
750 }
751 }
752
753 // undo normalization of loading factors
754 for(int i=0; i<nRows; i++){
755 for(int j=0; j<nColumns; j++){
756 rotatedLoadingFactorsAsRows[i][j] *= communalityWeights[j];
757 loadingFactorMatrix[i][j] *= communalityWeights[j];
758 }
759 }
760
761 return rotatedLoadingFactorsAsRows;
762 }
763
764 // Transpose a matrix (as a possible aide to the use of the static methods)
765 public static double[][] transposeMatrix(double[][] matrix){
766 int nRows = matrix.length;
767 int nColumns = matrix[0].length;
768 for(int i=1; i<nRows; i++)if(matrix[i].length!=nColumns)throw new IllegalArgumentException("All rows must be the same length");
769 double[][] transpose = new double[nColumns][nRows];
770 for(int i=0; i<nRows; i++){
771 for(int j=0; j<nColumns; j++){
772 transpose[j][i] = matrix[i][j];
773 }
774 }
775 return transpose;
776 }
777
778 // Varimax criterion calculation
779 public static double varimaxCriterion(double[][] loadingFactorMatrix){
780 int nRows = loadingFactorMatrix.length;
781 int nColumns = loadingFactorMatrix[0].length;
782 double va1 = 0.0;
783 double va2 = 0.0;
784 double va3 = 0.0;
785 for(int j=0; j<nRows; j++){
786 double sum1 = 0.0;
787 for(int k=0; k<nColumns; k++){
788 sum1 += Math.pow(loadingFactorMatrix[j][k], 4);
789 }
790 va1 += sum1;
791 }
792 //Db.show("STOP");
793 va1 *= nColumns;
794 for(int j=0; j<nRows; j++){
795 double sum2 = 0.0;
796 for(int k=0; k<nColumns; k++)sum2 += Math.pow(loadingFactorMatrix[j][k], 2);
797 va2 += sum2*sum2;
798 }
799 va3 = va1 - va2;
800
801 return va3;
802 }
803
804 // Varimax rotation angle calculation
805 // Kaiset maximization procedure
806 public static double varimaxAngle(double[][] loadingFactorMatrix, int k, int l){
807 int nColumns = loadingFactorMatrix[0].length;
808 double uTerm = 0.0;
809 double vTerm = 0.0;
810 double bigA = 0.0;
811 double bigB = 0.0;
812 double bigC = 0.0;
813 double bigD = 0.0;
814
815 for(int j=0; j<nColumns; j++){
816 double lmjk = loadingFactorMatrix[k][j];
817 double lmjl = loadingFactorMatrix[l][j];
818 uTerm = lmjk*lmjk - lmjl*lmjl;
819 vTerm = 2.0*lmjk*lmjl;
820 bigA += uTerm;
821 bigB += vTerm;
822 bigC += uTerm*uTerm - vTerm*vTerm;
823 bigD += 2.0*uTerm*vTerm;
824 }
825 double bigE = bigD - 2.0*bigA*bigB/nColumns;
826 double bigF = bigC - (bigA*bigA - bigB*bigB)/nColumns;
827 double angle = 0.25*Math.atan2(bigE, bigF);
828 return angle;
829 }
830
831 // Single rotation
832 public static double[][] singleRotation(double[][] loadingFactorMatrix, int k, int l, double angle){
833 int nRows = loadingFactorMatrix.length;
834 int nColumns = loadingFactorMatrix[0].length;
835 double[][] rotatedMatrix = new double[nRows][nColumns];
836 for(int i=0; i<nRows; i++){
837 for(int j=0; j<nColumns; j++){
838 rotatedMatrix[i][j] = loadingFactorMatrix[i][j];
839 }
840 }
841
842 double sinphi = Math.sin(angle);
843 double cosphi = Math.cos(angle);
844 for(int j=0; j<nColumns; j++){
845 rotatedMatrix[k][j] = loadingFactorMatrix[k][j]*cosphi + loadingFactorMatrix[l][j]*sinphi;
846 rotatedMatrix[l][j] = -loadingFactorMatrix[k][j]*sinphi + loadingFactorMatrix[l][j]*cosphi;
847 }
848 return rotatedMatrix;
849 }
850
851
852 // RETURN DATA
853
854 // Return eigenvalues as calculated
855 public double[] eigenValues(){
856 if(!this.pcaDone)this.pca();
857 return this.eigenValues;
858 }
859
860 // Return eigenvalues ordered into a descending order
861 public double[] orderedEigenValues(){
862 if(!this.pcaDone)this.pca();
863 return this.orderedEigenValues;
864 }
865
866 // Return indices of the eigenvalues before ordering into a descending order
867 public int[] eigenValueIndices(){
868 if(!this.pcaDone)this.pca();
869 return this.eigenValueIndices;
870 }
871
872 // Return sum of the eigenvalues
873 public double eigenValueTotal(){
874 if(!this.pcaDone)this.pca();
875 return this.eigenValueTotal;
876 }
877
878
879 // Return eigenvalues ordered into a descending order and expressed as a percentage of total
880 public double[] proportionPercentage(){
881 if(!this.pcaDone)this.pca();
882 return this.proportionPercentage;
883 }
884
885 // Return cumulative values of the eigenvalues ordered into a descending order and expressed as a percentage of total
886 public double[] cumulativePercentage(){
887 if(!this.pcaDone)this.pca();
888 return this.cumulativePercentage;
889 }
890
891 // Return scaled rotated eigenvalues
892 public double[] rotatedEigenValues(){
893 if(!this.rotationDone)throw new IllegalArgumentException("No rotation has been performed");
894 return this.rotatedEigenValues;
895 }
896
897 // Return scaled rotated eigenvalues as proportion of total variance
898 public double[] rotatedProportionPercentage(){
899 if(!this.rotationDone)throw new IllegalArgumentException("No rotation has been performed");
900 return this.rotatedProportionPercentage;
901 }
902
903 // Return scaled rotated eigenvalues as cumulative percentages
904 public double[] rotatedCumulativePercentage(){
905 if(!this.rotationDone)throw new IllegalArgumentException("No rotation has been performed");
906 return this.rotatedCumulativePercentage;
907 }
908
909
910
911 // Return eigenvectors as calculated
912 // Each column is the eigenvector for an eigenvalue
913 public double[][] eigenVectors(){
914 if(!this.pcaDone)this.pca();
915 return this.eigenVectorsAsColumns;
916 }
917
918 // Return eigenvectors as calculated
919 // Each row is the eigenvector for an eigenvalue
920 public double[][] eigenVectorsAsRows(){
921 if(!this.pcaDone)this.pca();
922 return this.eigenVectorsAsRows;
923 }
924
925 // Return eigenvector ordered to match the eigenvalues sorted into a descending order
926 // Each column is the eigenvector for an eigenvalue
927 public double[][] orderedEigenVectorsAsColumns(){
928 if(!this.pcaDone)this.pca();
929 return this.orderedEigenVectorsAsColumns;
930 }
931
932 // Return eigenvector ordered to match the eigenvalues sorted into a descending order
933 // Each column is the eigenvector for an eigenvalue
934 public double[][] orderedEigenVectors(){
935 if(!this.pcaDone)this.pca();
936 return this.orderedEigenVectorsAsColumns;
937 }
938
939 // Return eigenvector ordered to match the eigenvalues sorted into a descending order
940 // Each rowis the eigenvector for an eigenvalue
941 public double[][] orderedEigenVectorsAsRows(){
942 if(!this.pcaDone)this.pca();
943 return this.orderedEigenVectorsAsRows;
944 }
945
946 // Return loading factors ordered to match the eigenvalues sorted into a descending order
947 // Each column is the loading factors for an eigenvalue
948 public double[][] loadingFactorsAsColumns(){
949 if(!this.pcaDone)this.pca();
950 return this.loadingFactorsAsColumns;
951 }
952
953 // Return loading factors ordered to match the eigenvalues sorted into a descending order
954 // Each row is the loading factors for an eigenvalue
955 public double[][] loadingFactorsAsRows(){
956 if(!this.pcaDone)this.pca();
957 return this.loadingFactorsAsRows;
958 }
959
960 // Return rotated loading factors as columns
961 public double[][] rotatedLoadingFactorsAsColumns(){
962 if(!this.rotationDone)throw new IllegalArgumentException("No rotation has been performed");
963 return this.rotatedLoadingFactorsAsColumns;
964 }
965
966 // Return rotated loading factors as rows
967 public double[][] rotatedLoadingFactorsAsRows(){
968 if(!this.rotationDone)throw new IllegalArgumentException("No rotation has been performed");
969 return this.rotatedLoadingFactorsAsRows;
970 }
971
972 // Return communalities
973 public double[] communalities(){
974 if(!this.pcaDone)this.pca();
975 return this.communalities;
976 }
977
978 // Return communality weights
979 public double[] communalityWeights(){
980 if(!this.pcaDone)this.pca();
981 return this.communalityWeights;
982 }
983
984 // Return covariance matrix
985 public Matrix covarianceMatrix(){
986 if(!this.pcaDone)this.pca();
987 return this.covarianceMatrix;
988 }
989
990 // Return correlation matrix
991 public Matrix correlationMatrix(){
992 if(!this.pcaDone)this.pca();
993 return this.correlationMatrix;
994 }
995
996 // Return Monte Carlo means
997 public double[] monteCarloMeans(){
998 if(!this.monteCarloDone)this.monteCarlo();
999 return this.randomEigenValuesMeans;
1000 }
1001
1002 // Return Monte Carlo standard deviations
1003 public double[] monteCarloStandardDeviations(){
1004 if(!this.monteCarloDone)this.monteCarlo();
1005 return this.randomEigenValuesSDs;
1006 }
1007
1008 // Return Monte Carlo percentiles
1009 public double[] monteCarloPercentiles(){
1010 if(!this.monteCarloDone)this.monteCarlo();
1011 return this.randomEigenValuesPercentiles;
1012 }
1013
1014 // Return Monte Carlo eigenvalue matrix
1015 public double[][] monteCarloEigenValues(){
1016 if(!this.monteCarloDone)this.monteCarlo();
1017 return this.randomEigenValues;
1018 }
1019
1020 // Return original data matrix
1021 public Matrix originalData(){
1022 if(!this.pcaDone)this.pca();
1023 return this.data;
1024 }
1025
1026 // Return data minus row means divided by n-1 or n
1027 public Matrix xMatrix(){
1028 if(!this.pcaDone)this.pca();
1029 double denom = this.nItems;
1030 if(!super.nFactorOption)denom -= 1.0;
1031 Matrix mat = dataMinusMeans.times(1.0/Math.sqrt(denom));
1032 return mat;
1033 }
1034
1035 // Return transpose of data minus row means divided by n-1 or n
1036 public Matrix xMatrixTranspose(){
1037 if(!this.pcaDone)this.pca();
1038 double denom = this.nItems;
1039 if(!super.nFactorOption)denom -= 1.0;
1040 Matrix mat = dataMinusMeansTranspose.times(1.0/Math.sqrt(denom));
1041 return mat;
1042 }
1043
1044 // Return number of extracted components with eigenvalues greater than or equal to one
1045 public int nEigenOneOrGreater(){
1046 if(!this.pcaDone)this.pca();
1047 return this.greaterThanOneLimit;
1048 }
1049
1050 // Return number of extracted components with eigenvalues greater than the corresponding Monte Carlo mean
1051 public int nMeanCrossover(){
1052 if(!this.monteCarloDone)this.monteCarlo();
1053 return this.meanCrossover;
1054 }
1055
1056 // Return number of extracted components with eigenvalues greater than the corresponding Monte Carlo percentile
1057 public int nPercentileCrossover(){
1058 if(!this.monteCarloDone)this.monteCarlo();
1059 return this.percentileCrossover;
1060 }
1061
1062 // OUTPUT THE ANALYSIS
1063
1064 // Full analysis without output of input data
1065 // no input file name entered via method argument list
1066 public void analysis(){
1067
1068
1069 this.outputFilename = "PCAOutput";
1070 if(this.fileOption==1){
1071 this.outputFilename += ".txt";
1072 }
1073 else{
1074 this.outputFilename += ".xls";
1075 }
1076 String message1 = "Output file name for the analysis details:";
1077 String message2 = "\nEnter the required name (as a single word) and click OK ";
1078 String message3 = "\nor simply click OK for default value";
1079 String message = message1 + message2 + message3;
1080 String defaultName = this.outputFilename;
1081 this.outputFilename = Db.readLine(message, defaultName);
1082 this.analysis(this.outputFilename);
1083 }
1084
1085 // Full analysis without output of input data
1086 // input file name via method argument list
1087 public void analysis(String filename){
1088
1089 // Scree Plot
1090 this.screePlot();
1091
1092 // Open output file
1093 this.outputFilename = filename;
1094 String outputFilenameWithoutExtension = null;
1095 String extension = null;
1096 int pos = filename.indexOf('.');
1097 if(pos==-1){
1098 outputFilenameWithoutExtension = filename;
1099 if(this.fileOption==1){
1100 this.outputFilename += ".txt";
1101 }
1102 else{
1103 this.outputFilename += ".xls";
1104 }
1105 }
1106 else{
1107 extension = (filename.substring(pos)).trim();
1108
1109 outputFilenameWithoutExtension = (filename.substring(0, pos)).trim();
1110 if(extension.equalsIgnoreCase(".xls")){
1111 if(this.fileOption==1){
1112 if(this.fileOptionSet){
1113 String message1 = "Your entered output file type is .xls";
1114 String message2 = "\nbut you have chosen a .txt output";
1115 String message = message1 + message2;
1116 String headerComment = "Your output file name extension";
1117 String[] comments = {message, "replace it with .txt [text file]"};
1118 String[] boxTitles = {"Retain", ".txt"};
1119 int defaultBox = 1;
1120 int opt = Db.optionBox(headerComment, comments, boxTitles, defaultBox);
1121 if(opt==2)this.outputFilename = outputFilenameWithoutExtension + ".txt";
1122 }
1123 else{
1124 this.fileOption=2;
1125 }
1126 }
1127 }
1128
1129 if(extension.equalsIgnoreCase(".txt")){
1130 if(this.fileOption==2){
1131 if(this.fileOptionSet){
1132 String message1 = "Your entered output file type is .txt";
1133 String message2 = "\nbut you have chosen a .xls output";
1134 String message = message1 + message2;
1135 String headerComment = "Your output file name extension";
1136 String[] comments = {message, "replace it with .xls [Excel file]"};
1137 String[] boxTitles = {"Retain", ".xls"};
1138 int defaultBox = 1;
1139 int opt = Db.optionBox(headerComment, comments, boxTitles, defaultBox);
1140 if(opt==2)this.outputFilename = outputFilenameWithoutExtension + ".xls";
1141 }
1142 else{
1143 this.fileOption=1;
1144 }
1145 }
1146 }
1147
1148 if(!extension.equalsIgnoreCase(".txt") && !extension.equalsIgnoreCase(".xls")){
1149 String message1 = "Your extension is " + extension;
1150 String message2 = "\n Do you wish to retain it:";
1151 String message = message1 + message2;
1152 String headerComment = "Your output file name extension";
1153 String[] comments = {message, "replace it with .txt [text file]", "replace it with .xls [MS Excel file]"};
1154 String[] boxTitles = {"Retain", ".txt", ".xls"};
1155 int defaultBox = 1;
1156 int opt = Db.optionBox(headerComment, comments, boxTitles, defaultBox);
1157 switch(opt){
1158 case 1: this.fileOption=1;
1159 break;
1160 case 2: this.outputFilename = outputFilenameWithoutExtension + ".txt";
1161 this.fileOption=1;
1162 break;
1163 case 3: this.outputFilename = outputFilenameWithoutExtension + ".xls";
1164 this.fileOption=2;
1165 break;
1166 }
1167 }
1168 }
1169
1170 if(this.fileOption==1){
1171 this.analysisText();
1172 }
1173 else{
1174 this.analysisExcel();
1175 }
1176
1177 System.out.println("The analysis has been written to the file " + this.outputFilename);
1178 }
1179
1180 // Output analysis to a text (.txt) file
1181 private void analysisText(){
1182
1183 FileOutput fout = null;
1184 if(this.fileNumberingSet){
1185 fout = new FileOutput(this.outputFilename, 'n');
1186 }
1187 else{
1188 fout = new FileOutput(this.outputFilename);
1189 }
1190
1191 // perform PCA if not already performed
1192 if(!pcaDone)this.pca();
1193 if(!this.monteCarloDone)this.monteCarlo();
1194
1195 // output title
1196 fout.println("PRINCIPAL COMPONENT ANALYSIS");
1197 fout.println("Program: PCA - Analysis Output");
1198 for(int i=0; i<this.titleLines; i++)fout.println(title[i]);
1199 Date d = new Date();
1200 String day = DateFormat.getDateInstance().format(d);
1201 String tim = DateFormat.getTimeInstance().format(d);
1202 fout.println("Program executed at " + tim + " on " + day);
1203 fout.println();
1204 if(this.covRhoOption){
1205 fout.println("Covariance matrix used");
1206 }
1207 else{
1208 fout.println("Correlation matrix used");
1209 }
1210 fout.println();
1211
1212 // output eigenvalue table
1213 // field width
1214 int field1 = 10;
1215 int field2 = 12;
1216 int field3 = 2;
1217
1218 fout.println("ALL EIGENVALUES");
1219
1220 fout.print("Component ", field1);
1221 fout.print("Unordered ", field1);
1222 fout.print("Eigenvalue ", field2);
1223 fout.print("Proportion ", field2);
1224 fout.print("Cumulative ", field2);
1225 fout.println("Difference ");
1226
1227 fout.print(" ", field1);
1228 fout.print("index", field1);
1229 fout.print(" ", field2);
1230 fout.print("as % ", field2);
1231 fout.print("percentage ", field2);
1232 fout.println(" ");
1233
1234
1235
1236 for(int i=0; i<this.nItems; i++){
1237 fout.print(i+1, field1);
1238 fout.print((this.eigenValueIndices[i]+1), field1);
1239 fout.print(Fmath.truncate(this.orderedEigenValues[i], this.trunc), field2);
1240 fout.print(Fmath.truncate(this.proportionPercentage[i], this.trunc), field2);
1241 fout.print(Fmath.truncate(this.cumulativePercentage[i], this.trunc), field2);
1242 if(i<this.nItems-1){
1243 fout.print(Fmath.truncate((this.orderedEigenValues[i] - this.orderedEigenValues[i+1]), this.trunc), field2);
1244 }
1245 else{
1246 fout.print(" ", field2);
1247 }
1248 fout.print(" ", field3);
1249
1250 fout.println();
1251 }
1252 fout.println();
1253
1254
1255 // Extracted components
1256 int nMax = this.greaterThanOneLimit;
1257 if(nMax<this.meanCrossover)nMax=this.meanCrossover;
1258 if(nMax<this.percentileCrossover)nMax=this.percentileCrossover;
1259 fout.println("EXTRACTED EIGENVALUES");
1260 fout.print(" ", field1);
1261 fout.print("Greater than unity", 3*field2 + field3);
1262 fout.print("Greater than Monte Carlo Mean ", 3*field2 + field3);
1263 fout.println("Greater than Monte Carlo Percentile");
1264
1265 fout.print("Component ", field1);
1266 fout.print("Eigenvalue ", field2);
1267 fout.print("Proportion ", field2);
1268 fout.print("Cumulative ", field2);
1269 fout.print(" ", field3);
1270
1271 fout.print("Eigenvalue ", field2);
1272 fout.print("Proportion ", field2);
1273 fout.print("Cumulative ", field2);
1274 fout.print(" ", field3);
1275
1276 fout.print("Eigenvalue ", field2);
1277 fout.print("Proportion ", field2);
1278 fout.print("Cumulative ", field2);
1279 fout.println(" ");
1280
1281 fout.print(" ", field1);
1282 fout.print(" ", field2);
1283 fout.print("as % ", field2);
1284 fout.print("percentage ", field2);
1285 fout.print(" ", field3);
1286
1287 fout.print(" ", field2);
1288 fout.print("as % ", field2);
1289 fout.print("percentage ", field2);
1290 fout.print(" ", field3);
1291
1292 fout.print(" ", field2);
1293 fout.print("as % ", field2);
1294 fout.print("percentage ", field2);
1295 fout.println(" ");
1296
1297 int ii=0;
1298 while(ii<nMax){
1299 fout.print(ii+1, field1);
1300
1301 if(ii<this.greaterThanOneLimit){
1302 fout.print(Fmath.truncate(this.orderedEigenValues[ii], this.trunc), field2);
1303 fout.print(Fmath.truncate(this.proportionPercentage[ii], this.trunc), field2);
1304 fout.print(Fmath.truncate(this.cumulativePercentage[ii], this.trunc), (field2+field3));
1305 }
1306
1307 if(ii<this.meanCrossover){
1308 fout.print(Fmath.truncate(this.orderedEigenValues[ii], this.trunc), field2);
1309 fout.print(Fmath.truncate(this.proportionPercentage[ii], this.trunc), field2);
1310 fout.print(Fmath.truncate(this.cumulativePercentage[ii], this.trunc), (field2+field3));
1311 }
1312
1313 if(ii<this.percentileCrossover){
1314 fout.print(Fmath.truncate(this.orderedEigenValues[ii], this.trunc), field2);
1315 fout.print(Fmath.truncate(this.proportionPercentage[ii], this.trunc), field2);
1316 fout.print(Fmath.truncate(this.cumulativePercentage[ii], this.trunc));
1317 }
1318 fout.println();
1319 ii++;
1320 }
1321 fout.println();
1322
1323
1324 fout.println("PARALLEL ANALYSIS");
1325 fout.println("Number of simulations = " + this.nMonteCarlo);
1326 if(this.gaussianDeviates){
1327 fout.println("Gaussian random deviates used");
1328 }
1329 else{
1330 fout.println("Uniform random deviates used");
1331 }
1332 fout.println("Percentile value used = " + this.percentile + " %");
1333
1334 fout.println();
1335 fout.print("Component ", field1);
1336 fout.print("Data ", field2);
1337 fout.print("Proportion ", field2);
1338 fout.print("Cumulative ", field2);
1339 fout.print(" ", field3);
1340 fout.print("Data ", field2);
1341 fout.print("Monte Carlo ", field2);
1342 fout.print("Monte Carlo ", field2);
1343 fout.println("Monte Carlo ");
1344
1345 fout.print(" ", field1);
1346 fout.print("Eigenvalue ", field2);
1347 fout.print("as % ", field2);
1348 fout.print("percentage ", field2);
1349 fout.print(" ", field3);
1350 fout.print("Eigenvalue ", field2);
1351 fout.print("Eigenvalue ", field2);
1352 fout.print("Eigenvalue ", field2);
1353 fout.println("Eigenvalue ");
1354
1355 fout.print(" ", field1);
1356 fout.print(" ", field2);
1357 fout.print(" ", field2);
1358 fout.print(" ", field2);
1359 fout.print(" ", field3);
1360 fout.print(" ", field2);
1361 fout.print("Percentile ", field2);
1362 fout.print("Mean ", field2);
1363 fout.println("Standard Deviation ");
1364
1365 for(int i=0; i<this.nItems; i++){
1366 fout.print(i+1, field1);
1367 fout.print(Fmath.truncate(this.orderedEigenValues[i], this.trunc), field2);
1368 fout.print(Fmath.truncate(this.proportionPercentage[i], this.trunc), field2);
1369 fout.print(Fmath.truncate(this.cumulativePercentage[i], this.trunc), field2);
1370 fout.print(" ", field3);
1371 fout.print(Fmath.truncate(this.orderedEigenValues[i], this.trunc), field2);
1372 fout.print(Fmath.truncate(this.randomEigenValuesPercentiles[i], this.trunc), field2);
1373 fout.print(Fmath.truncate(this.randomEigenValuesMeans[i], this.trunc), field2);
1374 fout.println(Fmath.truncate(this.randomEigenValuesSDs[i], this.trunc));
1375 }
1376 fout.println();
1377
1378 // Correlation Matrix
1379 fout.println("CORRELATION MATRIX");
1380 fout.println("Original component indices in parenthesis");
1381 fout.println();
1382 fout.print(" ", field1);
1383 fout.print("component", field1);
1384 for(int i=0; i<this.nItems; i++)fout.print((this.eigenValueIndices[i]+1) + " (" + (i+1) + ")", field2);
1385 fout.println();
1386 fout.println("component");
1387 for(int i=0; i<this.nItems; i++){
1388 fout.print((this.eigenValueIndices[i]+1) + " (" + (i+1) + ")", 2*field1);
1389 for(int j=0; j<this.nItems; j++)fout.print(Fmath.truncate(this.correlationMatrix.getElement(j,i), this.trunc), field2);
1390 fout.println();
1391 }
1392 fout.println();
1393
1394 // Covariance Matrix
1395 fout.println("COVARIANCE MATRIX");
1396 fout.println("Original component indices in parenthesis");
1397 fout.println();
1398 fout.print(" ", field1);
1399 fout.print("component", field1);
1400 for(int i=0; i<this.nItems; i++)fout.print((this.eigenValueIndices[i]+1) + " (" + (i+1) + ")", field2);
1401 fout.println();
1402 fout.println("component");
1403 for(int i=0; i<this.nItems; i++){
1404 fout.print((this.eigenValueIndices[i]+1) + " (" + (i+1) + ")", 2*field1);
1405 for(int j=0; j<this.nItems; j++)fout.print(Fmath.truncate(this.covarianceMatrix.getElement(j,i), this.trunc), field2);
1406 fout.println();
1407 }
1408
1409 fout.println();
1410
1411 // Eigenvectors
1412 fout.println("EIGENVECTORS");
1413 fout.println("Original component indices in parenthesis");
1414 fout.println("Vector corresponding to an ordered eigenvalues in each row");
1415 fout.println();
1416 fout.print(" ", field1);
1417 fout.print("component", field1);
1418 for(int i=0; i<this.nItems; i++)fout.print((this.eigenValueIndices[i]+1) + " (" + (i+1) + ")", field2);
1419 fout.println();
1420 fout.println("component");
1421 for(int i=0; i<this.nItems; i++){
1422 fout.print((i+1) + " (" + (this.eigenValueIndices[i]+1) + ")", 2*field1);
1423 for(int j=0; j<this.nItems; j++)fout.print(Fmath.truncate(this.orderedEigenVectorsAsRows[i][j], this.trunc), field2);
1424 fout.println();
1425 }
1426 fout.println();
1427
1428 // Loading factors
1429 fout.println("LOADING FACTORS");
1430 fout.println("Original indices in parenthesis");
1431 fout.println("Loading factors corresponding to an ordered eigenvalues in each row");
1432 fout.println();
1433 fout.print(" ", field1);
1434 fout.print("component", field1);
1435 for(int i=0; i<this.nItems; i++)fout.print((this.eigenValueIndices[i]+1) + " (" + (i+1) + ")", field2);
1436 fout.print(" ", field1);
1437 fout.print("Eigenvalue", field2);
1438 fout.print("Proportion", field2);
1439 fout.println("Cumulative %");
1440 fout.println("factor");
1441 for(int i=0; i<this.nItems; i++){
1442 fout.print((i+1) + " (" + (this.eigenValueIndices[i]+1) + ")", 2*field1);
1443 for(int j=0; j<this.nItems; j++)fout.print(Fmath.truncate(this.loadingFactorsAsRows[i][j], this.trunc), field2);
1444 fout.print(" ", field1);
1445 fout.print(Fmath.truncate(this.orderedEigenValues[i], this.trunc), field2);
1446 fout.print(Fmath.truncate(proportionPercentage[i], this.trunc), field2);
1447 fout.println(Fmath.truncate(cumulativePercentage[i], this.trunc));
1448 }
1449 fout.println();
1450
1451 // Rotated loading factors
1452 fout.println("ROTATED LOADING FACTORS");
1453 if(this.varimaxOption){
1454 fout.println("NORMAL VARIMAX");
1455 }
1456 else{
1457 fout.println("RAW VARIMAX");
1458 }
1459
1460 String message = "The ordered eigenvalues with Monte Carlo means and percentiles in parenthesis";
1461 message += "\n (Total number of eigenvalues = " + this.nItems + ")";
1462 int nDisplay = this.nItems;
1463 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
1464 int screenHeight = screenSize.height;
1465 int nDisplayLimit = 20*screenHeight/800;
1466 if(nDisplay>nDisplay)nDisplay = nDisplayLimit;
1467 for(int i=0; i<nDisplay; i++){
1468 message += "\n " + Fmath.truncate(this.orderedEigenValues[i], 4) + " (" + Fmath.truncate(this.randomEigenValuesMeans[i], 4) + " " + Fmath.truncate(this.randomEigenValuesPercentiles[i], 4) + ")";
1469 }
1470 if(nDisplay<this.nItems)message += "\n . . . ";
1471 message += "\nEnter number of eigenvalues to be extracted";
1472 int nExtracted = this.greaterThanOneLimit;
1473 nExtracted = Db.readInt(message, nExtracted);
1474 this.varimaxRotation(nExtracted);
1475
1476 fout.println("Varimax rotation for " + nExtracted + " extracted factors");
1477 fout.println("Rotated loading factors and eigenvalues scaled to ensure total 'rotated variance' matches unrotated variance for the extracted factors");
1478 fout.println("Original indices in parenthesis");
1479 fout.println();
1480 fout.print(" ", field1);
1481 fout.print("component", field1);
1482 for(int i=0; i<this.nItems; i++)fout.print((this.rotatedIndices[i]+1) + " (" + (i+1) + ")", field2);
1483 fout.print(" ", field1);
1484 fout.print("Eigenvalue", field2);
1485 fout.print("Proportion", field2);
1486 fout.println("Cumulative %");
1487 fout.println("factor");
1488
1489 for(int i=0; i<nExtracted; i++){
1490 fout.print((i+1) + " (" + (rotatedIndices[i]+1) + ")", 2*field1);
1491 for(int j=0; j<this.nItems; j++)fout.print(Fmath.truncate(this.rotatedLoadingFactorsAsRows[i][j], this.trunc), field2);
1492 fout.print(" ", field1);
1493 fout.print(Fmath.truncate(rotatedEigenValues[i], this.trunc), field2);
1494 fout.print(Fmath.truncate(rotatedProportionPercentage[i], this.trunc), field2);
1495 fout.println(Fmath.truncate(rotatedCumulativePercentage[i], this.trunc));
1496 }
1497 fout.println();
1498
1499 fout.println("DATA USED");
1500 fout.println("Number of items = " + this.nItems);
1501 fout.println("Number of persons = " + this.nPersons);
1502
1503
1504 if(this.originalDataType==0){
1505 fout.printtab("Item");
1506 for(int i=0; i<this.nPersons; i++){
1507 fout.printtab(i+1);
1508 }
1509 fout.println();
1510 for(int i=0; i<this.nItems; i++){
1511 fout.printtab(this.itemNames[i]);
1512 for(int j=0; j<this.nPersons; j++){
1513 fout.printtab(Fmath.truncate(this.scores0[i][j], this.trunc));
1514 }
1515 fout.println();
1516 }
1517 }
1518 else{
1519 fout.printtab("Person");
1520 for(int i=0; i<this.nItems; i++){
1521 fout.printtab(this.itemNames[i]);
1522 }
1523 fout.println();
1524 for(int i=0; i<this.nPersons; i++){
1525 fout.printtab(i+1);
1526 for(int j=0; j<this.nItems; j++){
1527 fout.printtab(Fmath.truncate(this.scores1[i][j], this.trunc));
1528 }
1529 fout.println();
1530 }
1531 }
1532
1533 fout.close();
1534 }
1535
1536 // Output to an Excel readable file
1537 private void analysisExcel(){
1538
1539 FileOutput fout = null;
1540 if(this.fileNumberingSet){
1541 fout = new FileOutput(this.outputFilename, 'n');
1542 }
1543 else{
1544 fout = new FileOutput(this.outputFilename);
1545 }
1546
1547 // perform PCA if not already performed
1548 if(!pcaDone)this.pca();
1549 if(!this.monteCarloDone)this.monteCarlo();
1550
1551 // output title
1552 fout.println("PRINCIPAL COMPONENT ANALYSIS");
1553 fout.println("Program: PCA - Analysis Output");
1554 for(int i=0; i<this.titleLines; i++)fout.println(title[i]);
1555 Date d = new Date();
1556 String day = DateFormat.getDateInstance().format(d);
1557 String tim = DateFormat.getTimeInstance().format(d);
1558 fout.println("Program executed at " + tim + " on " + day);
1559 fout.println();
1560 if(this.covRhoOption){
1561 fout.println("Covariance matrix used");
1562 }
1563 else{
1564 fout.println("Correlation matrix used");
1565 }
1566 fout.println();
1567
1568 // output eigenvalue table
1569 fout.println("ALL EIGENVALUES");
1570
1571 fout.printtab("Component ");
1572 fout.printtab("Unordered ");
1573 fout.printtab("Eigenvalue ");
1574 fout.printtab("Proportion ");
1575 fout.printtab("Cumulative ");
1576 fout.println("Difference ");
1577
1578 fout.printtab(" ");
1579 fout.printtab("index");
1580 fout.printtab(" ");
1581 fout.printtab("as % ");
1582 fout.printtab("percentage ");
1583 fout.println(" ");
1584
1585
1586
1587 for(int i=0; i<this.nItems; i++){
1588 fout.printtab(i+1);
1589 fout.printtab((this.eigenValueIndices[i]+1));
1590 fout.printtab(Fmath.truncate(this.orderedEigenValues[i], this.trunc));
1591 fout.printtab(Fmath.truncate(this.proportionPercentage[i], this.trunc));
1592 fout.printtab(Fmath.truncate(this.cumulativePercentage[i], this.trunc));
1593 if(i<this.nItems-1){
1594 fout.printtab(Fmath.truncate((this.orderedEigenValues[i] - this.orderedEigenValues[i+1]), this.trunc));
1595 }
1596 else{
1597 fout.printtab(" ");
1598 }
1599 fout.printtab(" ");
1600
1601 fout.println();
1602 }
1603 fout.println();
1604
1605
1606 // Extracted components
1607 int nMax = this.greaterThanOneLimit;
1608 if(nMax<this.meanCrossover)nMax=this.meanCrossover;
1609 if(nMax<this.percentileCrossover)nMax=this.percentileCrossover;
1610 fout.println("EXTRACTED EIGENVALUES");
1611 fout.printtab(" ");
1612 fout.printtab("Greater than unity");
1613 fout.printtab(" ");fout.printtab(" ");fout.printtab(" ");
1614 fout.printtab("Greater than Monte Carlo Mean ");
1615 fout.printtab(" ");fout.printtab(" ");fout.printtab(" ");
1616 fout.println("Greater than Monte Carlo Percentile");
1617
1618 fout.printtab("Component ");
1619 fout.printtab("Eigenvalue ");
1620 fout.printtab("Proportion ");
1621 fout.printtab("Cumulative ");
1622 fout.printtab(" ");
1623
1624 fout.printtab("Eigenvalue ");
1625 fout.printtab("Proportion ");
1626 fout.printtab("Cumulative ");
1627 fout.printtab(" ");
1628
1629 fout.printtab("Eigenvalue ");
1630 fout.printtab("Proportion ");
1631 fout.printtab("Cumulative ");
1632 fout.println(" ");
1633
1634 fout.printtab(" ");
1635 fout.printtab(" ");
1636 fout.printtab("as % ");
1637 fout.printtab("percentage ");
1638 fout.printtab(" ");
1639
1640 fout.printtab(" ");
1641 fout.printtab("as % ");
1642 fout.printtab("percentage ");
1643 fout.printtab(" ");
1644
1645 fout.printtab(" ");
1646 fout.printtab("as % ");
1647 fout.printtab("percentage ");
1648 fout.println(" ");
1649
1650 int ii=0;
1651 while(ii<nMax){
1652 fout.printtab(ii+1);
1653
1654 if(ii<this.greaterThanOneLimit){
1655 fout.printtab(Fmath.truncate(this.orderedEigenValues[ii], this.trunc));
1656 fout.printtab(Fmath.truncate(this.proportionPercentage[ii], this.trunc));
1657 fout.printtab(Fmath.truncate(this.cumulativePercentage[ii], this.trunc));
1658 fout.printtab(" ");
1659 }
1660
1661 if(ii<this.meanCrossover){
1662 fout.printtab(Fmath.truncate(this.orderedEigenValues[ii], this.trunc));
1663 fout.printtab(Fmath.truncate(this.proportionPercentage[ii], this.trunc));
1664 fout.printtab(Fmath.truncate(this.cumulativePercentage[ii], this.trunc));
1665 fout.printtab(" ");
1666 }
1667
1668 if(ii<this.percentileCrossover){
1669 fout.printtab(Fmath.truncate(this.orderedEigenValues[ii], this.trunc));
1670 fout.printtab(Fmath.truncate(this.proportionPercentage[ii], this.trunc));
1671 fout.printtab(Fmath.truncate(this.cumulativePercentage[ii], this.trunc));
1672 }
1673 fout.println();
1674 ii++;
1675 }
1676 fout.println();
1677
1678
1679 fout.println("PARALLEL ANALYSIS");
1680 fout.println("Number of simulations = " + this.nMonteCarlo);
1681 if(this.gaussianDeviates){
1682 fout.println("Gaussian random deviates used");
1683 }
1684 else{
1685 fout.println("Uniform random deviates used");
1686 }
1687 fout.println("Percentile value used = " + this.percentile + " %");
1688
1689 fout.println();
1690 fout.printtab("Component ");
1691 fout.printtab("Data ");
1692 fout.printtab("Proportion ");
1693 fout.printtab("Cumulative ");
1694 fout.printtab(" ");
1695 fout.printtab("Data ");
1696 fout.printtab("Monte Carlo ");
1697 fout.printtab("Monte Carlo ");
1698 fout.println("Monte Carlo ");
1699
1700 fout.printtab(" ");
1701 fout.printtab("Eigenvalue ");
1702 fout.printtab("as % ");
1703 fout.printtab("percentage ");
1704 fout.printtab(" ");
1705 fout.printtab("Eigenvalue ");
1706 fout.printtab("Eigenvalue ");
1707 fout.printtab("Eigenvalue ");
1708 fout.println("Eigenvalue ");
1709
1710 fout.printtab(" ");
1711 fout.printtab(" ");
1712 fout.printtab(" ");
1713 fout.printtab(" ");
1714 fout.printtab(" ");
1715 fout.printtab(" ");
1716 fout.printtab("Percentile ");
1717 fout.printtab("Mean ");
1718 fout.println("Standard Deviation ");
1719
1720 for(int i=0; i<this.nItems; i++){
1721 fout.printtab(i+1);
1722 fout.printtab(Fmath.truncate(this.orderedEigenValues[i], this.trunc));
1723 fout.printtab(Fmath.truncate(this.proportionPercentage[i], this.trunc));
1724 fout.printtab(Fmath.truncate(this.cumulativePercentage[i], this.trunc));
1725 fout.printtab(" ");
1726 fout.printtab(Fmath.truncate(this.orderedEigenValues[i], this.trunc));
1727 fout.printtab(Fmath.truncate(this.randomEigenValuesPercentiles[i], this.trunc));
1728 fout.printtab(Fmath.truncate(this.randomEigenValuesMeans[i], this.trunc));
1729 fout.println(Fmath.truncate(this.randomEigenValuesSDs[i], this.trunc));
1730 }
1731 fout.println();
1732
1733 // Correlation Matrix
1734 fout.println("CORRELATION MATRIX");
1735 fout.println("Original component indices in parenthesis");
1736 fout.println();
1737 fout.printtab(" ");
1738 fout.printtab("component");
1739 for(int i=0; i<this.nItems; i++)fout.printtab((this.eigenValueIndices[i]+1) + " (" + (i+1) + ")");
1740 fout.println();
1741 fout.println("component");
1742 for(int i=0; i<this.nItems; i++){
1743 fout.printtab((this.eigenValueIndices[i]+1) + " (" + (i+1) + ")");
1744 fout.printtab(" ");
1745 for(int j=0; j<this.nItems; j++)fout.printtab(Fmath.truncate(this.correlationMatrix.getElement(j,i), this.trunc));
1746 fout.println();
1747 }
1748 fout.println();
1749
1750 // Covariance Matrix
1751 fout.println("COVARIANCE MATRIX");
1752 fout.println("Original component indices in parenthesis");
1753 fout.println();
1754 fout.printtab(" ");
1755 fout.printtab("component");
1756 for(int i=0; i<this.nItems; i++)fout.printtab((this.eigenValueIndices[i]+1) + " (" + (i+1) + ")");
1757 fout.println();
1758 fout.println("component");
1759 for(int i=0; i<this.nItems; i++){
1760 fout.printtab((this.eigenValueIndices[i]+1) + " (" + (i+1) + ")");
1761 fout.printtab(" ");
1762 for(int j=0; j<this.nItems; j++)fout.printtab(Fmath.truncate(this.covarianceMatrix.getElement(j,i), this.trunc));
1763 fout.println();
1764 }
1765 fout.println();
1766
1767 // Eigenvectors
1768 fout.println("EIGENVECTORS");
1769 fout.println("Original component indices in parenthesis");
1770 fout.println("Vector corresponding to an ordered eigenvalues in each row");
1771 fout.println();
1772 fout.printtab(" ");
1773 fout.printtab("component");
1774 for(int i=0; i<this.nItems; i++)fout.printtab((this.eigenValueIndices[i]+1) + " (" + (i+1) + ")");
1775 fout.println();
1776 fout.println("component");
1777
1778 for(int i=0; i<this.nItems; i++){
1779 fout.printtab((i+1) + " (" + (this.eigenValueIndices[i]+1) + ")");
1780 fout.printtab(" ");
1781 for(int j=0; j<this.nItems; j++)fout.printtab(Fmath.truncate(this.orderedEigenVectorsAsRows[i][j], this.trunc));
1782 fout.println();
1783 }
1784 fout.println();
1785
1786 // Loading factors
1787 fout.println("LOADING FACTORS");
1788 fout.println("Original indices in parenthesis");
1789 fout.println("Loading factors corresponding to an ordered eigenvalues in each row");
1790 fout.println();
1791 fout.printtab(" ");
1792 fout.printtab("component");
1793 for(int i=0; i<this.nItems; i++)fout.printtab((this.eigenValueIndices[i]+1) + " (" + (i+1) + ")");
1794 fout.printtab(" ");
1795 fout.printtab("Eigenvalue");
1796 fout.printtab("% Proportion");
1797 fout.println("Cumulative %");
1798 fout.println("factor");
1799 for(int i=0; i<this.nItems; i++){
1800 fout.printtab((i+1) + " (" + (this.eigenValueIndices[i]+1) + ")");
1801 fout.printtab(" ");
1802 for(int j=0; j<this.nItems; j++)fout.printtab(Fmath.truncate(this.loadingFactorsAsRows[i][j], this.trunc));
1803 fout.printtab(" ");
1804 fout.printtab(Fmath.truncate(this.orderedEigenValues[i], this.trunc));
1805 fout.printtab(Fmath.truncate(proportionPercentage[i], this.trunc));
1806 fout.println(Fmath.truncate(cumulativePercentage[i], this.trunc));
1807 }
1808 fout.println();
1809
1810 // Rotated loading factors
1811 fout.println("ROTATED LOADING FACTORS");
1812 if(this.varimaxOption){
1813 fout.println("NORMAL VARIMAX");
1814 }
1815 else{
1816 fout.println("RAW VARIMAX");
1817 }
1818
1819 String message = "The ordered eigenvalues with Monte Carlo means and percentiles in parenthesis";
1820 message += "\n (Total number of eigenvalues = " + this.nItems + ")";
1821 int nDisplay = this.nItems;
1822 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
1823 int screenHeight = screenSize.height;
1824 int nDisplayLimit = 20*screenHeight/800;
1825 if(nDisplay>nDisplay)nDisplay = nDisplayLimit;
1826 for(int i=0; i<nDisplay; i++){
1827 message += "\n " + Fmath.truncate(this.orderedEigenValues[i], 4) + " (" + Fmath.truncate(this.randomEigenValuesMeans[i], 4) + " " + Fmath.truncate(this.randomEigenValuesPercentiles[i], 4) + ")";
1828 }
1829 if(nDisplay<this.nItems)message += "\n . . . ";
1830 message += "\nEnter number of eigenvalues to be extracted";
1831 int nExtracted = this.greaterThanOneLimit;
1832 nExtracted = Db.readInt(message, nExtracted);
1833 this.varimaxRotation(nExtracted);
1834
1835 fout.println("Varimax rotation for " + nExtracted + " extracted factors");
1836 fout.println("Rotated loading factors and eigenvalues scaled to ensure total 'rotated variance' matches unrotated variance for the extracted factors");
1837 fout.println("Original indices in parenthesis");
1838 fout.println();
1839 fout.printtab(" ");
1840 fout.printtab("component");
1841 for(int i=0; i<this.nItems; i++)fout.printtab((this.rotatedIndices[i]+1) + " (" + (i+1) + ")");
1842 fout.printtab(" ");
1843 fout.printtab("Eigenvalue");
1844 fout.printtab("% Proportion");
1845 fout.println("Cumulative %");
1846 fout.println("factor");
1847 for(int i=0; i<nExtracted; i++){
1848 fout.printtab((i+1) + " (" + (this.rotatedIndices[i]+1) + ")");
1849 fout.printtab(" ");
1850 for(int j=0; j<this.nItems; j++)fout.printtab(Fmath.truncate(this.rotatedLoadingFactorsAsRows[i][j], this.trunc));
1851 fout.printtab(" ");
1852 fout.printtab(Fmath.truncate(rotatedEigenValues[i], this.trunc));
1853 fout.printtab(Fmath.truncate(rotatedProportionPercentage[i], this.trunc));
1854 fout.println(Fmath.truncate(rotatedCumulativePercentage[i], this.trunc));
1855 }
1856
1857
1858 fout.println();
1859
1860
1861 fout.println("DATA USED");
1862 fout.println("Number of items = " + this.nItems);
1863 fout.println("Number of persons = " + this.nPersons);
1864
1865 if(this.originalDataType==0){
1866 fout.printtab("Item");
1867 for(int i=0; i<this.nPersons; i++){
1868 fout.printtab(i+1);
1869 }
1870 fout.println();
1871 for(int i=0; i<this.nItems; i++){
1872 fout.printtab(this.itemNames[i]);
1873 for(int j=0; j<this.nPersons; j++){
1874 fout.printtab(Fmath.truncate(this.scores0[i][j], this.trunc));
1875 }
1876 fout.println();
1877 }
1878 }
1879 else{
1880 fout.printtab("Person");
1881 for(int i=0; i<this.nItems; i++){
1882 fout.printtab(this.itemNames[i]);
1883 }
1884 fout.println();
1885 for(int i=0; i<this.nPersons; i++){
1886 fout.printtab(i+1);
1887 for(int j=0; j<this.nItems; j++){
1888 fout.printtab(Fmath.truncate(this.scores1[i][j], this.trunc));
1889 }
1890 fout.println();
1891 }
1892 }
1893
1894 fout.close();
1895 }
1896}
1897
Note: See TracBrowser for help on using the repository browser.