double PCA_and_TableOfReal_getFractionVariance (PCA me, TableOfReal thee, long from, long to) { try { double fraction = NUMundefined; if (from < 1 || from > to || to > thy numberOfColumns) { return NUMundefined; } autoSSCP s = TableOfReal_to_SSCP (thee, 0, 0, 0, 0); autoSSCP sp = Eigen_and_SSCP_project (me, s.get()); fraction = SSCP_getFractionVariation (sp.get(), from, to); return fraction; } catch (MelderError) { return NUMundefined; } }
autoDiscriminant TableOfReal_to_Discriminant (TableOfReal me) { try { autoDiscriminant thee = Thing_new (Discriminant); long dimension = my numberOfColumns; if (! NUMdmatrix_hasFiniteElements(my data, 1, my numberOfRows, 1, my numberOfColumns)) { Melder_throw (U"At least one of the table's elements is not finite or undefined."); } if (! TableOfReal_hasRowLabels (me)) { Melder_throw (U"At least one of the rows has no label."); } autoTableOfReal mew = TableOfReal_sortOnlyByRowLabels (me); if (! TableOfReal_hasColumnLabels (mew.get())) { TableOfReal_setSequentialColumnLabels (mew.get(), 0, 0, U"c", 1, 1); } thy groups = TableOfReal_to_SSCPList_byLabel (mew.get()); thy total = TableOfReal_to_SSCP (mew.get(), 0, 0, 0, 0); if ((thy numberOfGroups = thy groups -> size) < 2) { Melder_throw (U"Number of groups must be greater than one."); } TableOfReal_centreColumns_byRowLabel (mew.get()); // Overall centroid and apriori probabilities and costs. autoNUMvector<double> centroid (1, dimension); autoNUMmatrix<double> between (1, thy numberOfGroups, 1, dimension); thy aprioriProbabilities = NUMvector<double> (1, thy numberOfGroups); thy costs = NUMmatrix<double> (1, thy numberOfGroups, 1, thy numberOfGroups); double sum = 0, scale; for (long k = 1; k <= thy numberOfGroups; k ++) { SSCP m = thy groups->at [k]; sum += scale = SSCP_getNumberOfObservations (m); for (long j = 1; j <= dimension; j ++) { centroid [j] += scale * m -> centroid [j]; } } for (long j = 1; j <= dimension; j ++) { centroid [j] /= sum; } for (long k = 1; k <= thy numberOfGroups; k ++) { SSCP m = thy groups->at [k]; scale = SSCP_getNumberOfObservations (m); thy aprioriProbabilities[k] = scale / my numberOfRows; for (long j = 1; j <= dimension; j ++) { between [k] [j] = sqrt (scale) * (m -> centroid [j] - centroid [j]); } } // We need to solve B'B.x = lambda W'W.x, where B'B and W'W are the between and within covariance matrices. // We do not calculate these covariance matrices directly from the data but instead use the GSVD to solve for // the eigenvalues and eigenvectors of the equation. thy eigen = Thing_new (Eigen); Eigen_initFromSquareRootPair (thy eigen.get(), between.peek(), thy numberOfGroups, dimension, mew -> data, my numberOfRows); // Default priors and costs for (long igroup = 1; igroup <= thy numberOfGroups; igroup ++) { for (long jgroup = igroup + 1; jgroup <= thy numberOfGroups; jgroup ++) { thy costs [igroup] [jgroup] = thy costs [jgroup] [igroup] = 1.0; } } return thee; } catch (MelderError) { Melder_throw (me, U": Discriminant not created."); } }