Data Analysis Mathematics Linear Algebra Statistics
New Version 7.0!  QuickStart Samples

# Factor Analysis (FA) QuickStart Sample (F#)

Illustrates how to perform a Factor Analysis using classes in the Extreme.Statistics.Multivariate namespace in F#.

```#light

open System

open Extreme.Mathematics
open Extreme.Mathematics.LinearAlgebra.IO
open Extreme.Statistics
open Extreme.Statistics.IO
open Extreme.Statistics.Multivariate

// Demonstrates how to use classes that implement
// Factor Analysis.

// This QuickStart Sample demonstrates how to perform
// a factor analysis on a set of data.
//
// The classes used in this sample reside in the
// Extreme.Statistics.Multivariate namespace.

// First, our dataset, 'm255.dta', from Professor James Sidanius.
//     See http://www.ats.ucla.edu/stat/sas/output/factor.htm

// Note: tolerances used to test for convergence in factor analysis
// algorithms are usually set very low (around 0.001). As a result,
// when comparing results from different programs, usually only
// about the first 3 digits will be equal.

// The data is in Stata format. Use a matrix reader to load it into a matrix.

// We'll use only these columns:
let names =
[|
"item13"; "item14"; "item15"; "item16"; "item17"; "item18";
"item19"; "item20"; "item21"; "item22"; "item23"; "item24"
|]
// First, filter out any rows with missing values:
let col = rawFrame.RemoveRowsWithMissingValues(names)

//
// Factor analysis
//

// We can construct FA objects in many ways. Since we have the data in a matrix,
// we use the constructor that takes a data matrix as input.
let fa = FactorAnalysis(col, names)
// We set the number of factors:
fa.NumberOfFactors <- 3
// and immediately perform the analysis:
fa.Compute()

// We can get the unrotated factors:
let unrotatedFactors = fa.GetUnrotatedFactors()
// We can get the contributions of each factor:
printfn " #    Eigenvalue Difference Contribution Contrib. %%"
for factor in unrotatedFactors do
// and write out its properties
printfn "%2d%12.4f%11.4f%14.3f%10.3f"
factor.Index factor.Eigenvalue factor.EigenvalueDifference
factor.ProportionOfVariance
factor.CumulativeProportionOfVariance

printfn "\nVarimax rotation"

printfn "Variable        1          2          3      Uniqueness"
for i in 0..names.Length-1 do
printfn "  %8s%10.5f %10.5f %10.5f%10.5f"
names.[i]
fa.Uniqueness.[i]

// Now we'll look at the rotated factors:
let rotatedFactors = fa.GetRotatedFactors()
printfn " #    Variance   Difference Proportion   Cumulative"
for factor in rotatedFactors do
printfn "%2d%12.4f%11s%13.4f%11.4f"
factor.Index factor.VarianceExplained "-"
factor.ProportionOfVariance
factor.CumulativeProportionOfVariance

printfn "Variable        1          2          3      Uniqueness"
for i in 0..names.Length-1 do
printfn "  %8s%10.5f %10.5f %10.5f%10.5f"
names.[i]
fa.Uniqueness.[i]

// And the matrix that rotates the factors
printfn "Factor transformation matrix:\n%s" (fa.FactorTransformationMatrix.ToString("F4"))

printfn "\nPromax rotation (power = 3)"

// Now let's use an (oblique) Promax rotation:
fa.RotationMethod <- FactorRotationMethod.Promax
fa.PromaxPower <- 3.0
fa.Compute()

// Now we'll look at the rotated factors:
printfn "\nRotated factor variance explained:"
let rotatedFactors2 = fa.GetRotatedFactors()
printfn " #    Variance"
for factor in rotatedFactors2 do
printfn "%2d%12.4f" factor.Index factor.VarianceExplained

printfn "Variable        1          2          3   Communality Uniqueness"
for i in 0..names.Length-1 do
// and write out its properties
printfn "  %8s%10.5f%10.5f%10.5f%10.5f %10.5f"
names.[i]
fa.Communalities.[i]
fa.Uniqueness.[i]

printfn "\nRotated factor structure:"
printfn "Variable        1          2          3"
for i in 0..names.Length-1 do
// and write out its properties
printfn "  %8s%10.5f %10.5f %10.5f"
names.[i]
rotatedFactors2..Structure.[i]
rotatedFactors2..Structure.[i]
rotatedFactors2..Structure.[i]

// For oblique rotations, the factors are usually correlated:
printfn "Factor correlation matrix:\n%s" (fa.FactorCorrelationMatrix.ToString("F4"))

//
// Factor analysis on a correlation matrix
//

printfn "\nUsing a correlation matrix"

// This example is from Exploratory Factor Analysis
// http://www.oup.com/us/companion.websites/9780199734177/supplementary/example/
let values =
[|
1.000; 0.666; 0.150; 0.617; 0.541; 0.653; 0.473; 0.549; 0.566;
0.666; 1.000; 0.247; 0.576; 0.510; 0.642; 0.425; 0.544; 0.488;
0.150; 0.247; 1.000; 0.222; 0.081; 0.164; 0.091; 0.181; 0.120;
0.617; 0.576; 0.222; 1.000; 0.409; 0.560; 0.338; 0.448; 0.349;
0.541; 0.510; 0.081; 0.409; 1.000; 0.667; 0.734; 0.465; 0.754;
0.653; 0.642; 0.164; 0.560; 0.667; 1.000; 0.596; 0.540; 0.672;
0.473; 0.425; 0.091; 0.338; 0.734; 0.596; 1.000; 0.432; 0.718;
0.549; 0.544; 0.181; 0.448; 0.465; 0.540; 0.432; 1.000; 0.412;
0.566; 0.488; 0.120; 0.349; 0.754; 0.672; 0.718; 0.412; 1.000
|]

let R = Matrix.CreateSymmetric(9, values, MatrixTriangle.Upper,
MatrixElementOrder.ColumnMajor, true)
let fa2 = new FactorAnalysis(R, FactorMethod.Correlation)
fa2.NumberOfFactors <- 2
fa2.ExtractionMethod <- FactorExtractionMethod.MaximumLikelihood
fa2.RotationMethod <- FactorRotationMethod.Varimax
fa2.Compute()

let names2 =
[|
"ComSt"; "PhyHlp"; "Encour"; "Tutor"
|]

// Here are the initial:
printfn "Variable     Initial    Extracted"
for i in 0..names2.Length-1 do
// and write out its properties
printfn "  %8s%10.5f %10.5f"
names2.[i]
fa2.InitialCommunalities.[i]
fa2.Communalities.[i]

// Note that in the SPSS output, the ordering of the variables
// is different.
let unrotatedFactors2 = fa2.GetUnrotatedFactors()
printfn "Variable        1          2"
for i in 0..names2.Length-1 do
// and write out its properties
printfn "  %8s%10.5f %10.5f"
names2.[i]