Factor Analysis (FA) in Visual Basic QuickStart Sample
Illustrates how to perform a Factor Analysis using classes in the Numerics.NET.Statistics.Multivariate namespace in Visual Basic.
Option Infer On
Imports Numerics.NET.Data.Stata
Imports Numerics.NET
Imports Numerics.NET.Statistics.Multivariate
' <summary>
' Demonstrates how to use classes that implement
' Factor Analysis.
' </summary>
Module FactorAnalysisExample
Sub Main()
' The license is verified at runtime. We're using
' a 30 day trial key here. For more information, see
' https://numerics.net/trial-key
Numerics.NET.License.Verify("64542-18980-57619-62268")
' This QuickStart Sample demonstrates how to perform
' a factor analysis on a set of data.
'
' The classes used in this sample reside in the
' Numerics.NET.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.
Dim frame = StataFile.ReadDataFrame("..\..\..\..\Data\m255.dta")
' We'll use only these columns:
Dim names As String() = {"item13", "item14", "item15", "item16",
"item17", "item18", "item19", "item20", "item21",
"item22", "item23", "item24"}
' First, filter out any rows with missing values:
frame = frame.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.
Dim fa As New FactorAnalysis(frame, names)
' We set the number of factors:
fa.NumberOfFactors = 3
' and immediately perform the analysis:
fa.Fit()
' We can get the unrotated factors:
Dim unrotatedFactors = fa.GetUnrotatedFactors()
' We can get the contributions of each factor:
Console.WriteLine(" # Eigenvalue Difference Contribution Contrib. %")
For Each factor As Factor In unrotatedFactors
' and write out its properties
Console.WriteLine("{0,2}{1,12:F4}{2,11:F4}{3,14:F3}{4,10:F3}",
factor.Index, factor.Eigenvalue, factor.EigenvalueDifference,
factor.ProportionOfVariance,
factor.CumulativeProportionOfVariance)
Next
Console.WriteLine(Environment.NewLine + "Varimax rotation")
' Here are the loadings for each of the variables:
Console.WriteLine(Environment.NewLine + "Unrotated loadings:")
Console.WriteLine("Variable 1 2 3 Uniqueness")
For i As Integer = 0 To names.Length - 1
Console.WriteLine(" {0,8}{1,10:F5} {2,10:F5} {3,10:F5}{4,10:F5}",
names(i),
unrotatedFactors(0).Loadings(i),
unrotatedFactors(1).Loadings(i),
unrotatedFactors(2).Loadings(i),
fa.Uniqueness(i))
Next
' Now we'll look at the rotated factors:
Dim rotatedFactors = fa.GetRotatedFactors()
Console.WriteLine(" # Variance Difference Proportion Cumulative")
For Each factor As Factor In rotatedFactors
Console.WriteLine("{0,2}{1,12:F4}{2,11:F4}{3,13:F4}{4,11:F4}",
factor.Index, factor.VarianceExplained, "-",
factor.ProportionOfVariance,
factor.CumulativeProportionOfVariance)
Next
' Here are the rotated loadings for each of the variables:
Console.WriteLine(Environment.NewLine + "Rotated loadings (Varimax):")
Console.WriteLine("Variable 1 2 3 Uniqueness")
For i As Integer = 0 To names.Length - 1
Console.WriteLine(" {0,8}{1,10:F5} {2,10:F5} {3,10:F5}{4,10:F5}",
names(i),
rotatedFactors(0).Loadings(i),
rotatedFactors(1).Loadings(i),
rotatedFactors(2).Loadings(i),
fa.Uniqueness(i))
Next
' And the matrix that rotates the factors
Console.WriteLine("Factor transformation matrix:" + Environment.NewLine + "{0:F4}",
fa.FactorTransformationMatrix)
Console.WriteLine(Environment.NewLine + "Promax rotation (power = 3)")
' Now let's use an (oblique) Promax rotation:
fa.RotationMethod = FactorRotationMethod.Promax
fa.PromaxPower = 3
fa.Fit()
' Now we'll look at the rotated factors:
Console.WriteLine(Environment.NewLine + "Rotated factor variance explained:")
rotatedFactors = fa.GetRotatedFactors()
Console.WriteLine(" # Variance")
For Each factor As Factor In rotatedFactors
Console.WriteLine("{0,2}{1,12:F4}",
factor.Index, factor.VarianceExplained)
Next
' Here are the rotated loadings for each of the variables:
Console.WriteLine(Environment.NewLine + "Rotated loadings/pattern (Promax):")
Console.WriteLine("Variable 1 2 3 Communality Uniqueness")
For i As Integer = 0 To names.Length - 1
' and write out its properties
Console.WriteLine(" {0,8}{1,10:F5}{2,10:F5}{3,10:F5}{4,10:F5} {5,10:F5}",
names(i),
rotatedFactors(0).Loadings(i),
rotatedFactors(1).Loadings(i),
rotatedFactors(2).Loadings(i),
fa.Communalities(i),
fa.Uniqueness(i))
Next
' Here are the rotated loadings for each of the variables:
Console.WriteLine(Environment.NewLine + "Rotated factor structure:")
Console.WriteLine("Variable 1 2 3")
For i As Integer = 0 To names.Length - 1
' and write out its properties
Console.WriteLine(" {0,8}{1,10:F5} {2,10:F5} {3,10:F5}",
names(i),
rotatedFactors(0).Structure(i),
rotatedFactors(1).Structure(i),
rotatedFactors(2).Structure(i))
Next
' For oblique rotations, the factors are usually correlated:
Console.WriteLine("Factor correlation matrix:" + Environment.NewLine + "{0:F4}",
fa.FactorCorrelationMatrix)
'
' Factor analysis on a correlation matrix
'
Console.WriteLine(Environment.NewLine + "Using a correlation matrix")
' This example is from Exploratory Factor Analysis
' http://www.oup.com/us/companion.websites/9780199734177/supplementary/example/
Dim values As Double() = {
1.0, 0.666, 0.15, 0.617, 0.541, 0.653, 0.473, 0.549, 0.566,
0.666, 1.0, 0.247, 0.576, 0.51, 0.642, 0.425, 0.544, 0.488,
0.15, 0.247, 1.0, 0.222, 0.081, 0.164, 0.091, 0.181, 0.12,
0.617, 0.576, 0.222, 1.0, 0.409, 0.56, 0.338, 0.448, 0.349,
0.541, 0.51, 0.081, 0.409, 1.0, 0.667, 0.734, 0.465, 0.754,
0.653, 0.642, 0.164, 0.56, 0.667, 1.0, 0.596, 0.54, 0.672,
0.473, 0.425, 0.091, 0.338, 0.734, 0.596, 1.0, 0.432, 0.718,
0.549, 0.544, 0.181, 0.448, 0.465, 0.54, 0.432, 1.0, 0.412,
0.566, 0.488, 0.12, 0.349, 0.754, 0.672, 0.718, 0.412, 1.0
}
Dim R = Matrix.CreateSymmetric(9, values,
MatrixTriangle.Upper, MatrixElementOrder.ColumnMajor, True)
fa = New FactorAnalysis(R, FactorMethod.Correlation)
fa.NumberOfFactors = 2
fa.ExtractionMethod = FactorExtractionMethod.MaximumLikelihood
fa.RotationMethod = FactorRotationMethod.Varimax
fa.Fit()
names = New String() {"Hugs", "Comps", "PerAd", "SocAd", "ProAd",
"ComSt", "PhyHlp", "Encour", "Tutor"}
' Here are the initial:
Console.WriteLine(Environment.NewLine + "Rotated factor loadings:")
Console.WriteLine("Variable Initial Extracted")
For i As Integer = 0 To names.Length - 1
Console.WriteLine(" {0,8}{1,10:F5} {2,10:F5}",
names(i),
fa.InitialCommunalities(i),
fa.Communalities(i))
Next
' Here are the rotated loadings for each of the variables:
' Note that in the SPSS output, the ordering of the variables
' is different.
unrotatedFactors = fa.GetUnrotatedFactors()
Console.WriteLine(Environment.NewLine + "Unrotated factor loadings:")
Console.WriteLine("Variable 1 2")
For i As Integer = 0 To names.Length - 1
Console.WriteLine(" {0,8}{1,10:F5} {2,10:F5}",
names(i),
unrotatedFactors(0).Loadings(i),
unrotatedFactors(1).Loadings(i))
Next
' Here are the rotated loadings for each of the variables:
rotatedFactors = fa.GetRotatedFactors()
Console.WriteLine(Environment.NewLine + "Rotated factor loadings:")
Console.WriteLine("Variable 1 2")
For i As Integer = 0 To names.Length - 1
Console.WriteLine(" {0,8}{1,10:F5} {2,10:F5}",
names(i),
rotatedFactors(0).Loadings(i),
rotatedFactors(1).Loadings(i))
Next
Console.Write("Press any key to exit.")
Console.ReadLine()
End Sub
End Module