public static PCAResults PCA(String csvPath, int numberOfFactors) { try { REngine engine; //init the R engine engine = getInststance(); csvPath = csvPath.Replace('\\', '/'); //executing script if (numberOfFactors > 0) { engine.Evaluate("library(psych)\n" + "data <- read.csv('" + csvPath + "', sep = ';')\n" + "pca <- principal(data, " + numberOfFactors + ", rotate='varimax')\n" + "pcaTable <- as.data.frame.matrix(rbind(pca$values, pca$values/sum(pca$values)*100, cumsum(pca$values), cumsum(pca$values/sum(pca$values)*100)))\n" + "loadings <- as.data.frame.matrix(t(pca$loadings))"); } else { engine.Evaluate("library(psych)\n" + "data <- read.csv('" + csvPath + "', sep = ';')\n" + "pca <- principal(data, rotate='varimax')\n" + "pcaTable <- as.data.frame.matrix(rbind(pca$values, pca$values/sum(pca$values)*100, cumsum(pca$values), cumsum(pca$values/sum(pca$values)*100)))\n" + "loadings <- as.data.frame.matrix(t(pca$loadings))"); } PCAResults pCAResults = new PCAResults(); pCAResults.pcaTable = engine.GetSymbol("pcaTable").AsDataFrame(); pCAResults.loadings = engine.GetSymbol("loadings").AsDataFrame(); Clear(); return(pCAResults); } catch (Exception e) { Console.WriteLine(e.StackTrace); return(null); } }
private void buttonRunACP_Click(object sender, EventArgs e) { using (var form = new ACPForm(viewModel.getNumberOfQuestions())) { form.PropertyChanged += this.viewModel.Parallel; var result = form.ShowDialog(); if (result == DialogResult.OK) { PCAResults results = this.viewModel.ACP(form.viewModel.factorNumber); if (results != null) { dataGridPrincipalComponents.DataSource = DataTableManager.PCATableToDataTable(results.pcaTable); dataGridPCALoadings.DataSource = DataTableManager.PCALoadingstoDataTable(results.loadings); } else { MessageBox.Show("An error has been occured or number of chosen factors is more than the number of questions", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } factorisationResults.Visible = true; } } }
/// <summary> /// Calculates a matrix which transforms a set of signals to a the principal components of those signals. /// </summary> /// <param name="channels"></param> /// <param name="length"></param> /// <returns>Returns a matrix which transforms the channels (after being normalized) into the principal components</returns> public static PCAResults CalculateMatrix(double[][] channels, int length) { var result = new PCAResults(); // Initilize Matrix and copy channels. double[][] matrix = new double[channels.Length][]; double[][] channels2 = new double[channels.Length][]; for (int i = 0; i < channels.Length; i++) { matrix[i] = new double[channels.Length]; channels2[i] = channels[i].ToArray(); } double[] sdSumByComponent = new double[channels.Length + 1]; // We add an extra "null component" to make our following code easier. // Iterate to calculate it. for (int componentIndex = 0; componentIndex < channels.Length; componentIndex++) { var p = InternalCalculateP(channels2, length); matrix[componentIndex] = p.ToArray(); // Subtract the current component from the data. double[] channelMeans = (from currentChannel in channels2 select currentChannel.Average()).ToArray(); double[] channelSDs = new double[channels.Length]; for (int channelIndex = 0; channelIndex < channels.Length; channelIndex++) { channelSDs[channelIndex] = Math.Pow((from sample in channels2[channelIndex] select Math.Pow((sample - channelMeans[channelIndex]), 2.0)).Average(), 0.5); } sdSumByComponent[componentIndex] = (from x in channelSDs select x * x).Sum(); result.MeansByStage.Add(channelMeans.ToArray()); result.StandardDeviationByStage.Add(channelSDs.ToArray()); for (int sampleIndex = 0; sampleIndex < length; sampleIndex++) { double dotProduct = 0.0; for (int channelIndex = 0; channelIndex < channels.Length; channelIndex++) { var channel = channels2[channelIndex]; double sample = channel[sampleIndex]; // Normalize sample. var sample_n = (sample - channelMeans[channelIndex]) / channelSDs[channelIndex]; dotProduct += sample_n * p[channelIndex]; channel[sampleIndex] = sample; } for (int channelIndex = 0; channelIndex < channels.Length; channelIndex++) { var channel = channels2[channelIndex]; double sample = channel[sampleIndex]; double sample_n = (sample - channelMeans[channelIndex]) / channelSDs[channelIndex]; // Subtract x*p. sample_n -= p[channelIndex] * dotProduct; double sample_p = (sample_n * channelSDs[channelIndex]) + channelMeans[channelIndex]; channel[sampleIndex] = sample_p; } } } double[] varExplainedByComponent = new double[channels.Length]; //Calculate the portion of variance explained by component. for (int componentIndex = 0; componentIndex < channels.Length; componentIndex++) { varExplainedByComponent[componentIndex] = (sdSumByComponent[componentIndex] - sdSumByComponent[componentIndex + 1]) / sdSumByComponent[0]; } result.Matrix = matrix; result.VarianceExplainedByComponent = varExplainedByComponent; return(result); }