CNL Stat : Multivariate Analysis : discriminant_analysis
discriminant_analysis
Performs a linear or a quadratic discriminant function analysis among several known groups.
Synopsis
#include <imsls.h>
void imsls_f_discriminant_analysis (int n_rows, int n_variables, float x[], int n_groups, 0)
The type double function is imsls_d_discriminant_analysis.
Required Arguments
int n_rows (Input)
Number of rows of x to be processed.
int n_variables (Input)
Number of variables to be used in the discrimination.
float x[] (Input)
Array of size n_rows by n_variables + 1 containing the data. The first n_variables columns correspond to the variables, and the last column (column n_variables) contains the group numbers. The groups must be numbered 1, 2, ..., n_groups.
int n_groups (Input)
Number of groups in the data.
Synopsis with Optional Arguments
#include <imsls.h>
void imsls_f_discriminant_analysis (int n_rows, int n_variables, float x[], int n_groups,
IMSLS_X_COL_DIM, int x_col_dim,
IMSLS_X_INDICES, int igrp, int ind[], int ifrq, int iwt,
IMSLS_METHOD, int method,
IMSLS_IDO, int ido,
IMSLS_ROWS_ADD, or
IMSLS_ROWS_DELETE,
IMSLS_PRIOR_EQUAL, or
IMSLS_PRIOR_PROPORTIONAL, or
IMSLS_PRIOR_INPUT, float prior_input[],
IMSLS_PRIOR_OUTPUT, float **prior_output,
IMSLS_PRIOR_OUTPUT_USER, float prior_output[],
IMSLS_GROUP_COUNTS, int **gcounts,
IMSLS_GROUP_COUNTS_USER, int gcounts[]
IMSLS_MEANS, float **means,
IMSLS_MEANS_USER, float means[],
IMSLS_COV, float **covariances,
IMSLS_COV_USER, float covariances[],
IMSLS_COEF, float **coefficients,
IMSLS_COEF_USER, float coefficients[],
IMSLS_CLASS_MEMBERSHIP, int **class_membership,
IMSLS_CLASS_MEMBERSHIP_USER, int class_membership[],
IMSLS_CLASS_TABLE, float **class_table,
IMSLS_CLASS_TABLE_USER, float class_table[],
IMSLS_PROB, float **prob,
IMSLS_PROB_USER, float prob[],
IMSLS_MAHALANOBIS, float **d2,
IMSLS_MAHALANOBIS_USER, float d2[],
IMSLS_STATS, float **stats,
IMSLS_STATS_USER, float stats[],
IMSLS_N_ROWS_MISSING, int *nrmiss,
0)
Optional Arguments
IMSLS_X_COL_DIM, int x_col_dim (Input)
Column dimension of array x.
Default: x_col_dim = n_variables + 1
IMSLS_X_INDICES, int igrp, int ind[], int ifrq, int iwt (Input)
Each of the four arguments contains indices indicating column numbers of x in which particular types of data are stored. Columns are numbered 0  x_col_dim  1.
Parameter igrp contains the index for the column of x in which the group numbers are stored.
Parameter ind contains the indices of the variables to be used in the analysis.
Parameters ifrq and iwt contain the column numbers of x in which the frequencies and weights, respectively, are stored. Set ifrq = 1 if there will be no column for frequencies. Set iwt = 1 if there will be no column for weights. Weights are rounded to the nearest integer. Negative weights are not allowed.
Defaults: igrp = n_variables, ind[] = 0, 1, ..., n_variables  1, ifrq = 1, and iwt = 1
IMSLS_METHOD, int method (Input)
Method of discrimination. The method chosen determines whether linear or quadratic discrimination is used, whether the group covariance matrices are computed (the pooled covariance matrix is always computed), and whether the leaving-out-one or the reclassification method is used to classify each observation.
method
discrimination method
covariances computed
classification method
1
linear
pooled, group
reclassification
2
quadratic
pooled, group
reclassification
3
linear
pooled
reclassification
4
linear
pooled, group
leaving-out-one
5
quadratic
pooled, group
leaving-out-one
6
linear
pooled
leaving-out-one
In the leaving-out-one method of classification, the posterior probabilities are adjusted so as to eliminate the effect of the observation from the sample statistics prior to its classification. In the classification method, the effect of the observation is not eliminated from the classification function.
When optional argument IMSLS_IDO is specified, the following rules for mixing methods apply; Methods 1, 2, 4, and 5 can be intermixed, as can methods 3 and 6. Methods 1, 2, 4, and 5 cannot be intermixed with methods 3 and 6.
Default: method = 1
IMSLS_IDO, int ido (Input)
Processing option. See Comments 3 and 4 for more information.
ido
Action
0
This is the only invocation; all the data are input at once. (Default)
1
This is the first invocation with this data; additional calls will be made. Initialization and updating for the n_rows observations of x will be performed.
2
This is an intermediate invocation; updating for the n_rows observations of x will be performed.
3
All statistics are updated for the n_rows observations. The discriminant functions and other statistics are computed.
4
The discriminant functions are used to classify each of the n_rows observations of x.
5
The covariance matrices are computed, and workspace is released. No further call to discriminant_analysis with ido greater than 1 should be made without first calling discriminant_analysis with ido = 1.
6
Workspace is released. No further calls to discriminant_analysis with ido greater than 1 should be made without first calling discriminant_analysis with ido = 1. Invo­cation with this option is not required if a call has already been made with ido = 5.
Default: ido = 0
IMSLS_ROWS_ADD (Input)
or
IMSLS_ROWS_DELETE (Input)
By default (or if IMSLS_ROWS_ADD is specified), then the observations in x are added to the discriminant statistics. If IMSLS_ROWS_DELETE is specified, then the observations are deleted.
If ido = 0, these optional arguments are ignored (data is always added if there is only one invocation).
IMSLS_PRIOR_EQUAL (Input)
or
IMSLS_PRIOR_PROPORTIONAL (Input)
or
IMSLS_PRIOR_INPUT, float prior_input[] (Input)
By default, (or if IMSLS_PRIOR_EQUAL is specified), equal prior probabilities are calculated as 1.0/n_groups.
If IMSLS_PRIOR_PROPORTIONAL is specified, prior probabilities are calculated to be proportional to the sample size in each group.
If IMSLS_PRIOR_INPUT is specified, then array prior_input is an array of length n_groups containing the prior probabilities for each group, such that the sum of all prior probabilities is equal to 1.0. Prior probabilities are not used if ido is equal to 1, 2, 5, or 6.
IMSLS_PRIOR_OUTPUT, float **prior_output (Output)
Address of a pointer to an array of length n_groups containing the most recently calculated or input prior probabilities. If IMSLS_PRIOR_PROPORTIONAL is specified, every element of prior_output is equal to 1 until a call is made with ido equal to 0 or 3, at which point the priors are calculated. Note that subsequent calls to discriminant_analysis with IMSLS_PRIOR_PROPORTIONAL specified, and ido not equal to 0 or 3 will result in the elements of prior_output being reset to 1.
IMSLS_PRIOR_OUTPUT_USER, float prior_output[] (Output)
Storage for array prior_output is provided by the user. See IMSLS_PRIOR_OUTPUT.
IMSLS_GROUP_COUNTS, int **gcounts (Output)
Address of a pointer to an integer array of length n_groups containing the number of observations in each group. Array gcounts is updated when ido is equal to 0, 1, or 2.
IMSLS_GROUP_COUNTS_USER, int gcounts[] (Output)
Storage for integer array gcounts is provided by the user. See IMSLS_GROUP_COUNTS.
IMSLS_MEANS, float **means (Output)
Address of a pointer to an array of size n_groups by n_variables. The i-th row of means contains the group i variable means. Array means is updated when ido is equal to 0, 1, 2, or 5. The means are unscaled until a call is made with ido = 5, where the unscaled means are calculated as Σwifi xi and the scaled means as
where xi is the value of the i-th observation, wi is the weight of the i-th observation, and fi is the frequency of the i-th observation.
IMSLS_MEANS_USER, float means[] (Output)
Storage for array means is provided by the user. See IMSLS_MEANS.
IMSLS_COV, float **covariances (Output)
Address of a pointer to an array of size g by n_variables by n_variables containing the within-group covariance matrices (methods 1, 2, 4, and 5 only) as the first g-1 matrices, and the pooled covariance matrix as the g-th matrix (that is, the first n_variables × n_variables elements comprise the group 1 covariance matrix, the next n_variables × n_variables elements comprise the group 2 covariance, ..., and the last n_variables × n_variables elements comprise the pooled covariance matrix). If method is 3 or 6 then g is equal to 1. Otherwise, g is equal to n_groups + 1. Argument cov is updated when ido is equal to 0, 1, 2, 3, or 5.
IMSLS_COV_USER, float covariances[] (Output)
Storage for array covariances is provided by the user. See IMSLS_COVARIANCES.
IMSLS_COEF, float **coefficients (Output)
Address of a pointer to an array of size n_groups by (n_variables + 1) containing the linear discriminant coefficients. The first column of coefficients contains the constant term, and the remaining columns contain the variable coefficients. Row i  1 of coefficients corresponds to group i, for i = 1, 2,  n_groups. Array coefficients is always computed as the linear discriminant function coefficients even when quadratic discrimination is specified. Specifically, given the linear discriminant function
the intercept is assigned to coefficients[i×(n_variables+1)] and the j‑th element of is assigned to coefficients[i×(n_variables+1)+j], where i = 0, n_groups-1 and j=1, n_variables+1. Array coefficients is updated when ido is equal to 0 or 3.
IMSLS_COEF_USER, float coefficients[] (Output)
Storage for array coefficients is provided by the user. See IMSLS_COEFFICIENTS.
IMSLS_CLASS_MEMBERSHIP, int **class_membership (Output)
Address of a pointer to an integer array of length n_rows containing the group to which the observation was classified. Array class_membership is updated when ido is equal to 0 or 4.
If an observation has an invalid group number, frequency, or weight when the leaving-out-one method has been specified, then the observation is not classified and the corresponding elements of class_membership (and prob, see IMSLS_PROB) are set to zero.
IMSLS_CLASS_MEMBERSHIP_USER, int class_membership[] (Ouput)
Storage for array class_membership is provided by the user. See IMSLS_CLASS_MEMBERSHIP.
IMSLS_CLASS_TABLE, float **class_table (Output)
Address of a pointer to an array of size n_groups by n_groups containing the classification table. Array class_table is updated when ido is equal to 0, 1, or 4. Each observation that is classified and has a group number 1.0, 2.0, ..., n_groups is entered into the table. The rows of the table correspond to the known group membership. The columns refer to the group to which the observation was classified. Classification results accumulate with each call to imsls_f_discriminant_analysis with ido equal to 4. For example, if two calls with ido equal to 4 are made, the elements in class_table sum to the total number of valid observations in the two calls.
IMSLS_CLASS_TABLE_USER, float class_table[] (Output)
Storage for array class_table is provided by the user. See IMSLS_CLASS_TABLE.
IMSLS_PROB, float **prob (Output)
Address of a pointer to an array of size n_rows by n_groups containing the posterior probabilities for each observation. Argument prob is updated when ido is equal to 0 or 4.
IMSLS_PROB_USER, float prob[] (Output)
Storage for array prob is provided by the user. See IMSLS_PROB.
IMSLS_MAHALANOBIS, float **d2 (Output)
Address of a pointer to an array of size n_groups by n_groups containing the Mahalanobis distances
between the group means. Argument d2 is updated when ido is equal to 0 or 3.
For linear discrimination, the Mahalanobis distance is computed using the pooled covariance matrix. Otherwise, the Mahalanobis distance
between group means i and j is computed using the within covariance matrix for group i in place of the pooled covariance matrix.
IMSLS_MAHALANOBIS_USER, float d2[] (Output)
Storage for array d2 is provided by the user. See IMSLS_MAHALANOBIS.
IMSLS_STATS, float **stats (Output)
Address of a pointer to an array of length 4 + 2 × (n_groups + 1) containing various statistics of interest. Array stats is updated when ido is equal to 0, 2, 3, or 5. The first element of stats is the sum of the degrees of freedom for the within-covariance matrices. The second, third, and fourth elements of stats correspond to the chi-squared statistic, its degrees of freedom, and the probability of a greater chi-squared, respectively, of a test of the homogeneity of the within-covariance matrices (not computed if method is equal to 3 or 6). The fifth through 5 + n_groups elements of stats contain the log of the determinants of each group’s covariance matrix (not computed if method is equal to 3 or 6) and of the pooled covariance matrix (element 4 + n_groups). Finally, the last n_groups + 1 elements of stats contain the sum of the weights within each group, and in the last position, the sum of the weights in all groups.
IMSLS_STATS_USER, float stats[] (Output)
Storage for array stats is provided by the user. See IMSLS_STATS_USER.
IMSLS_N_ROWS_MISSING, int *nrmiss (Output)
Number of rows of data encountered in calls to discriminant_analysis containing missing values (NaN) for the classification, group, weight, and/or frequency variables. If a row of data contains a missing value (NaN) for any of these variables, that row is excluded from the computations.
Array nrmiss is updated when ido is equal to 0, 1, 2, or 3.
Comments
1. Common choices for the Bayesian prior probabilities are given by:
prior_input[i] = 1.0n_groups (equal priors)
prior_input[i] = gcounts[i]n_rows (proportional priors)
prior_input[i] = Past history or subjective judgment.
In all cases, the priors should sum to 1.0.
2. Two passes of the data are made. In the first pass, the statistics required to compute the discriminant functions are obtained (ido equal to 1, 2, and 3). In the second pass, the discriminant functions are used to classify the observations. When ido is equal to 0, all of the data are memory resident, and both passes are made in one call to imsls_f_discriminant_analysis. When ido > 0 (optional argument IMSLS_IDO is specified), a third call to imsls_f_discriminant_analysis involving no data is required with ido equal to 5 or 6.
3. Here are a few rules and guidelines for the correct value of ido in a series of calls:
a. Calls with ido = 0 or ido = 1 may be made at any time, subject to rule 2. These calls indicate that a new analysis is to begin, and therefore allocate memory and destroy all statistics from previous calls.
b. Each series of calls to imsls_f_discriminant_analysis which begins with ido = 1 must end with ido equal to 5 or 6 to ensure the proper release of workspace, subject to rule 3.
c. ido may not be 4 or 5 before a call with ido = 3 has been made.
d. ido may not be 2, 3, 4, 5, or 6
i)   Immediately after a call with ido = 0.
ii)  Before a call with ido = 1 has been made.
iii) Immediately after a call with ido equal to 5 or 6 has been made.
The following is a valid sequence of ido’s:
ido
Explanation
0
Data Set A: Perform a complete analysis. All data to be used in the analysis must be present in x. Since cleanup of workspace is automatic for ido = 0, no further calls are necessary.
1
Data Set B: Begin analysis. The n_rows observations in x are used for initialization.
2
Data Set B: Continue analysis. New observations placed in x are added to (or deleted from, see IMSLS_ROWS_DELETE) the analysis.
2
Data Set B: Continue analysis. n_rows new observations placed in x are added to (or deleted from, see IMSLS_ROWS_DELETE) the analysis.
3
Data Set B: Continue analysis. n_rows new observations are added (or deleted) and discriminant functions and other statistics are computed.
4
Data Set B: Classification of each of the n_rows observations in the current x matrix.
5
Data Set B: End analysis. Covariance matrices are computed and workspace is released. This analysis could also have been ended by choosing ido = 6
1
Data Set C: Begin analysis. Note that for this call to be valid the previous call must have been made with ido equal to 5 or 6.
3
Data Set C: Continue analysis.
4
Data Set C: Continue analysis.
3
Data Set C: Continue analysis.
6
Data Set C: End analysis.
4. Because of the internal workspace allocation and saved variables, function imsls_f_discriminant_analysis must complete the analysis of a data set before beginning processing of the next data set.
Description
Function imsls_f_discriminant_analysis performs discriminant function analysis using either linear or quadratic discrimination. The output includes a measure of distance between the groups, a table summarizing the classification results, a matrix containing the posterior probabilities of group membership for each observation, and the within-sample means and covariance matrices. The linear discriminant function coefficients are also computed.
By default (or if optional argument IMSLS_IDO is specified with ido = 0) all observations are input during one call, a method of operation that has the advantage of simplicity. Alternatively, one or more rows of observations can be input during separate calls. This method does not require that all observations be memory resident, a significant advantage with large data sets. Note, however, that the algorithm requires two passes of the data. During the first pass the discriminant functions are computed while in the second pass, the observations are classified. Thus, with the second method of operation, the data will usually need to be input twice.
Because both methods result in the same operations being performed, the algorithm is discussed as if only a few observations are input during each call. The operations performed during each call depend upon the ido parameter.
The ido = 1 step is the initialization step. “Private” internally allocated saved variables corresponding to means, class_table, and covariances are initialized to zero, and other program parameters are set (copies of these private variables are written to the corresponding output variables upon return from the function call, assuming ido values such that the results are to be returned). Parameters n_rows, x, and method can be changed from one call to the next within the two sets {1, 2, 4, 5} and {3, 6} but not between these sets when ido > 1. That is, do not specify method = 1 in one call and method = 3 in another call without first making a call with ido = 1.
After initialization has been performed in the ido = 1 step, the within-group means are updated for all valid observations in x. Observations with invalid group numbers are ignored, as are observation with missing values. The LU factorization of the covariance matrices are updated by adding (or deleting) observations via Givens rotations.
The ido = 2 step is used solely for adding or deleting observations from the model as in the above paragraph.
The ido = 3 step begins by adding all observations in x to the means and the factorizations of the covariance matrices. It continues by computing some statistics of interest: the linear discriminant functions, the prior probabilities (by default, or if IMSLS_PROPORTIONAL_PRIORS is specified), the log of the determinant of each of the covariance matrices, a test statistic for testing that all of the within-group covariance matrices are equal, and a matrix of Mahalanobis distances between the groups. The matrix of Mahalanobis distances is computed via the pooled covariance matrix when linear discrimination is specified; the row covariance matrix is used when the discrimination is quadratic.
Covariance matrices are defined as follows: Let Ni denote the sum of the frequencies of the observations in group i and Mi denote the number of observations in group i. Then, if Si denotes the within-group i covariance matrix,
Where wj is the weight of the j-th observation in group i, fj is the frequency, xj is the j-th observation column vector (in group i), and denotes the mean vector of the observations in group i. The mean vectors are computed as
Given the means and the covariance matrices, the linear discriminant function for group i is computed as:
where ln (pi) is the natural log of the prior probability for the i-th group, x is the observation to be classified, and Sp denoted the pooled covariance matrix.
Let S denote either the pooled covariance matrix of one of the within-group covariance matrices Si. (S will be the pooled covariance matrix in linear discrimination, and Si otherwise.) The Mahalanobis distance between group i and group j is computed as:
Finally, the asymptotic chi-squared test for the equality of covariance matrices is computed as follows (Morrison 1976, p. 252):
where ni is the number of degrees of freedom in the i-th sample covariance matrix, k is the number of groups, and
where p is the number of variables.
When ido = 4, the estimated posterior probability of each observation x belonging to group i is computed using the prior probabilities and the sample mean vectors and estimated covariance matrices under a multivariate normal assumption. Under quadratic discrimination, the within-group covariance matrices are used to compute the estimated posterior probabilities. The estimated posterior probability of an observation x belonging to group i is
where
For the leaving-out-one method of classification (method equal to 4, 5 or 6), the sample mean vector and sample covariance matrices in the formula for
are adjusted so as to remove the observation x from their computation. For linear discrimination (method equal to 1, 3, 4, or 6), the linear discriminant function coefficients are actually used to compute the same posterior probabilities.
Using the posterior probabilities, each observation in x is classified into a group; the result is tabulated in the matrix class_table and saved in the vector class_membership. Matrix class_table is not altered at this stage if x[i][igrp] (see optional argument IMSLS_X_INDICES) contains a group number that is out of range. If the reclassification method is specified, then all observations with no missing values in the n_variables classification variables are classified. When the leaving-out-one method is used, observations with invalid group numbers, weights, frequencies, or classification variables are not classified. Regardless of the frequency, a 1 is added (or subtracted) from class_table for each row of x that is classified and contains a valid group number.
When method > 3, adjustment is made to the posterior probabilities to remove the effect of the observation in the classification rule. In this adjustment, each observation is presumed to have a weight of x[i][iwt] if iwt > 1 (and a weight of 1.0 if iwt = 1), and a frequency of 1.0. See Lachenbruch (1975, p. 36) for the required adjustment.
Finally, when ido = 5, the covariance matrices are computed from their LU factorizations. Internally allocated and saved variables are cleaned up at this step (ido equal to 5 or 6).
Examples
Example 1
The following example uses liner discrimination with equal prior probabilities on Fisher’s (1936) Iris data. This example illustrates the execution of imsls_f_discriminant_analysis when one call is made (i.e. using the default of ido = 0).
 
#include <imsls.h>
#include <stdio.h>
#include <stdlib.h>
 
int main() {
int n_groups = 3;
int nrow, nvar, ncol, nrmiss;
float *x, *xtemp;
float *prior_out, *means, *cov, *coef;
float *table, *d2, *stats, *prob;
int *counts, *cm;
static int perm[5] = {1, 2, 3, 4, 0};
 
/* Retrieve the Fisher Iris Data Set */
xtemp = imsls_f_data_sets(3,
IMSLS_N_OBSERVATIONS, &nrow,
IMSLS_N_VARIABLES, &ncol,
0);
 
nvar = ncol - 1;
 
/* Move the group column to end of the the matrix */
x = imsls_f_permute_matrix(nrow, ncol, xtemp, perm,
IMSLS_PERMUTE_COLUMNS,
0);
 
imsls_free(xtemp);
 
imsls_f_discriminant_analysis (nrow, nvar, x, n_groups,
IMSLS_METHOD, 3,
IMSLS_GROUP_COUNTS, &counts,
IMSLS_COEF, &coef,
IMSLS_MEANS, &means,
IMSLS_STATS, &stats,
IMSLS_CLASS_MEMBERSHIP, &cm,
IMSLS_CLASS_TABLE, &table,
IMSLS_PROB, &prob,
IMSLS_MAHALANOBIS, &d2,
IMSLS_COV, &cov,
IMSLS_PRIOR_OUTPUT, &prior_out,
IMSLS_N_ROWS_MISSING, &nrmiss,
IMSLS_PRIOR_EQUAL,
IMSLS_METHOD, 3,
0);
 
imsls_i_write_matrix("Counts", 1, n_groups, counts,
0);
imsls_f_write_matrix("Coef", n_groups, nvar+1, coef,
0);
imsls_f_write_matrix("Means", n_groups, nvar, means,
0);
imsls_f_write_matrix("Stats", 12, 1, stats,
0);
imsls_i_write_matrix("Membership", 1, nrow, cm,
0);
imsls_f_write_matrix("Table", n_groups, n_groups, table,
0);
imsls_f_write_matrix("Prob", nrow, n_groups, prob,
0);
imsls_f_write_matrix("D2", n_groups, n_groups, d2,
0);
imsls_f_write_matrix("Covariance", nvar, nvar, cov,
0);
imsls_f_write_matrix("Prior OUT", 1, n_groups, prior_out,
0);
 
printf("\nnrmiss = %3d\n", nrmiss);
 
free(means);
free(stats);
free(counts);
free(coef);
free(cm);
free(table);
free(prob);
free(d2);
free(prior_out);
free(cov);
}
Output
 
Counts
1 2 3
50 50 50
 
Coef
1 2 3 4 5
1 -86.3 23.5 23.6 -16.4 -17.4
2 -72.9 15.7 7.1 5.2 6.4
3 -104.4 12.4 3.7 12.8 21.1
 
Means
1 2 3 4
1 5.006 3.428 1.462 0.246
2 5.936 2.770 4.260 1.326
3 6.588 2.974 5.552 2.026
 
Stats
1 147
2 ..........
3 ..........
4 ..........
5 ..........
6 ..........
7 ..........
8 -10
9 50
10 50
11 50
12 150
 
Membership
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
 
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
 
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2
 
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
2 2 2 2 2 2 2 2 2 2 3 2 2 2 2 2 2 2 2 2
 
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
2 2 2 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
 
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
2 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
 
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
 
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
3 3 2 3 3 3 3 3 3 3 3 3 3 3 3 3
 
148 149 150
3 3 3
 
Table
1 2 3
1 50 0 0
2 0 48 2
3 0 1 49
 
Prob
1 2 3
1 1.000 0.000 0.000
2 1.000 0.000 0.000
3 1.000 0.000 0.000
4 1.000 0.000 0.000
5 1.000 0.000 0.000
6 1.000 0.000 0.000
7 1.000 0.000 0.000
8 1.000 0.000 0.000
9 1.000 0.000 0.000
10 1.000 0.000 0.000
11 1.000 0.000 0.000
12 1.000 0.000 0.000
13 1.000 0.000 0.000
14 1.000 0.000 0.000
15 1.000 0.000 0.000
16 1.000 0.000 0.000
17 1.000 0.000 0.000
18 1.000 0.000 0.000
19 1.000 0.000 0.000
20 1.000 0.000 0.000
21 1.000 0.000 0.000
22 1.000 0.000 0.000
23 1.000 0.000 0.000
24 1.000 0.000 0.000
25 1.000 0.000 0.000
26 1.000 0.000 0.000
27 1.000 0.000 0.000
28 1.000 0.000 0.000
29 1.000 0.000 0.000
30 1.000 0.000 0.000
31 1.000 0.000 0.000
32 1.000 0.000 0.000
33 1.000 0.000 0.000
34 1.000 0.000 0.000
35 1.000 0.000 0.000
36 1.000 0.000 0.000
37 1.000 0.000 0.000
38 1.000 0.000 0.000
39 1.000 0.000 0.000
40 1.000 0.000 0.000
41 1.000 0.000 0.000
42 1.000 0.000 0.000
43 1.000 0.000 0.000
44 1.000 0.000 0.000
45 1.000 0.000 0.000
46 1.000 0.000 0.000
47 1.000 0.000 0.000
48 1.000 0.000 0.000
49 1.000 0.000 0.000
50 1.000 0.000 0.000
51 0.000 1.000 0.000
52 0.000 0.999 0.001
53 0.000 0.996 0.004
54 0.000 1.000 0.000
55 0.000 0.996 0.004
56 0.000 0.999 0.001
57 0.000 0.986 0.014
58 0.000 1.000 0.000
59 0.000 1.000 0.000
60 0.000 1.000 0.000
61 0.000 1.000 0.000
62 0.000 0.999 0.001
63 0.000 1.000 0.000
64 0.000 0.994 0.006
65 0.000 1.000 0.000
66 0.000 1.000 0.000
67 0.000 0.981 0.019
68 0.000 1.000 0.000
69 0.000 0.960 0.040
70 0.000 1.000 0.000
71 0.000 0.253 0.747
72 0.000 1.000 0.000
73 0.000 0.816 0.184
74 0.000 1.000 0.000
75 0.000 1.000 0.000
76 0.000 1.000 0.000
77 0.000 0.998 0.002
78 0.000 0.689 0.311
79 0.000 0.993 0.007
80 0.000 1.000 0.000
81 0.000 1.000 0.000
82 0.000 1.000 0.000
83 0.000 1.000 0.000
84 0.000 0.143 0.857
85 0.000 0.964 0.036
86 0.000 0.994 0.006
87 0.000 0.998 0.002
88 0.000 0.999 0.001
89 0.000 1.000 0.000
90 0.000 1.000 0.000
91 0.000 0.999 0.001
92 0.000 0.998 0.002
93 0.000 1.000 0.000
94 0.000 1.000 0.000
95 0.000 1.000 0.000
96 0.000 1.000 0.000
97 0.000 1.000 0.000
98 0.000 1.000 0.000
99 0.000 1.000 0.000
100 0.000 1.000 0.000
101 0.000 0.000 1.000
102 0.000 0.001 0.999
103 0.000 0.000 1.000
104 0.000 0.001 0.999
105 0.000 0.000 1.000
106 0.000 0.000 1.000
107 0.000 0.049 0.951
108 0.000 0.000 1.000
109 0.000 0.000 1.000
110 0.000 0.000 1.000
111 0.000 0.013 0.987
112 0.000 0.002 0.998
113 0.000 0.000 1.000
114 0.000 0.000 1.000
115 0.000 0.000 1.000
116 0.000 0.000 1.000
117 0.000 0.006 0.994
118 0.000 0.000 1.000
119 0.000 0.000 1.000
120 0.000 0.221 0.779
121 0.000 0.000 1.000
122 0.000 0.001 0.999
123 0.000 0.000 1.000
124 0.000 0.097 0.903
125 0.000 0.000 1.000
126 0.000 0.003 0.997
127 0.000 0.188 0.812
128 0.000 0.134 0.866
129 0.000 0.000 1.000
130 0.000 0.104 0.896
131 0.000 0.000 1.000
132 0.000 0.001 0.999
133 0.000 0.000 1.000
134 0.000 0.729 0.271
135 0.000 0.066 0.934
136 0.000 0.000 1.000
137 0.000 0.000 1.000
138 0.000 0.006 0.994
139 0.000 0.193 0.807
140 0.000 0.001 0.999
141 0.000 0.000 1.000
142 0.000 0.000 1.000
143 0.000 0.001 0.999
144 0.000 0.000 1.000
145 0.000 0.000 1.000
146 0.000 0.000 1.000
147 0.000 0.006 0.994
148 0.000 0.003 0.997
149 0.000 0.000 1.000
150 0.000 0.018 0.982
 
D2
1 2 3
1 0.0 89.9 179.4
2 89.9 0.0 17.2
3 179.4 17.2 0.0
 
Covariance
1 2 3 4
1 0.2650 0.0927 0.1675 0.0384
2 0.0927 0.1154 0.0552 0.0327
3 0.1675 0.0552 0.1852 0.0427
4 0.0384 0.0327 0.0427 0.0419
 
Prior OUT
1 2 3
0.3333 0.3333 0.3333
 
nrmiss = 0
Example 2
Continuing with Fisher’s Iris data, the example below computes the quadratic discriminant functions using values of IDO greater than 0. In the first loop, all observations are added to the functions, one at a time. In the second loop, each of the observations is classified, one by one, using the leaving-out-one method.
 
#include <stdio.h>
#include <stdlib.h>
#include <imsls.h>
 
int main() {
int n_groups = 3;
int nrow, nvar, ncol, i, nrmiss;
float *x, *xtemp;
float *prior_out, *means, *cov, *coef;
float *table, *d2, *stats, *prob;
int *counts, *cm;
int perm[5] = {1, 2, 3, 4, 0};
 
/* Retrieve the Fisher Iris Data Set */
xtemp = imsls_f_data_sets(3,
IMSLS_N_OBSERVATIONS, &nrow,
IMSLS_N_VARIABLES, &ncol,
0);
 
nvar = ncol - 1;
 
/* Move the group column to end of the the matrix */
x = imsls_f_permute_matrix(nrow, ncol, xtemp, perm,
IMSLS_PERMUTE_COLUMNS,
0);
 
imsls_free(xtemp);
 
prior_out = (float *) malloc(n_groups*sizeof(float));
counts = (int *) malloc(n_groups*sizeof(int));
means = (float *) malloc(n_groups*nvar*sizeof(float));
cov = (float *) malloc(nvar*nvar*(n_groups+1)*sizeof(float));
coef = (float *) malloc(n_groups*(nvar+1)*sizeof(float));
table = (float *) malloc(n_groups*n_groups*sizeof(float));
d2 = (float *) malloc(n_groups*n_groups*sizeof(float));
stats = (float *) malloc((4+2*(n_groups+1))*sizeof(float));
cm = (int *) malloc(nrow*sizeof(int));
prob = (float *) malloc(nrow*n_groups*sizeof(float));
 
/*Initialize Analysis*/
imsls_f_discriminant_analysis (0, nvar, x, n_groups,
IMSLS_IDO, 1,
IMSLS_METHOD, 2,
0);
 
/*Add In Each Observation*/
for (i=0;i<nrow;i=i+1) {
imsls_f_discriminant_analysis (1, nvar, (x+i*ncol), n_groups,
IMSLS_IDO, 2,
0);
}
 
/*Remove observation 0 from the analysis */
imsls_f_discriminant_analysis (1, nvar, (x+0), n_groups,
IMSLS_ROWS_DELETE,
IMSLS_IDO, 2,
0);
 
/*Add observation 0 back into the analysis */
imsls_f_discriminant_analysis (1, nvar, (x+0), n_groups,
IMSLS_IDO, 2,
0);
 
/*Compute statistics*/
imsls_f_discriminant_analysis (0, nvar, x, n_groups,
IMSLS_PRIOR_PROPORTIONAL,
IMSLS_PRIOR_OUTPUT_USER, prior_out,
IMSLS_IDO, 3,
0);
 
imsls_f_write_matrix("Prior OUT", 1, n_groups, prior_out, 0);
 
/*Classify One observation at a time, using proportional priors*/
for (i=0;i<nrow;i=i+1) {
imsls_f_discriminant_analysis (1, nvar, (x+i*ncol), n_groups,
IMSLS_IDO, 4,
IMSLS_CLASS_MEMBERSHIP_USER, (cm+i),
IMSLS_PROB_USER, (prob+i*n_groups),
0);
}
 
/*Compute covariance matrices and release internal workspace*/
imsls_f_discriminant_analysis (0, nvar, x, n_groups,
IMSLS_IDO, 5,
IMSLS_COV_USER, cov,
IMSLS_GROUP_COUNTS_USER, counts,
IMSLS_COEF_USER, coef,
IMSLS_MEANS_USER, means,
IMSLS_STATS_USER, stats,
IMSLS_CLASS_TABLE_USER, table,
IMSLS_MAHALANOBIS_USER, d2,
IMSLS_N_ROWS_MISSING, &nrmiss, 0);
 
imsls_i_write_matrix("Counts", 1, n_groups, counts, 0);
imsls_f_write_matrix("Coef", n_groups, nvar+1, coef, 0);
imsls_f_write_matrix("Means", n_groups, nvar, means, 0);
imsls_f_write_matrix("Stats", 12, 1, stats, 0);
imsls_i_write_matrix("Membership", 1, nrow, cm, 0);
imsls_f_write_matrix("Table", n_groups, n_groups, table, 0);
imsls_f_write_matrix("Prob", nrow, n_groups, prob, 0);
imsls_f_write_matrix("D2", n_groups, n_groups, d2, 0);
imsls_f_write_matrix("Covariance", nvar, nvar, cov, 0);
printf("\nnrmiss = %3d\n", nrmiss);
 
free(means);
free(stats);
free(counts);
free(coef);
free(cm);
free(table);
free(prob);
free(d2);
free(prior_out);
free(cov);
}
Output
 
Prior OUT
1 2 3
0.3333 0.3333 0.3333
 
Counts
1 2 3
50 50 50
 
Coef
1 2 3 4 5
1 -86.3 23.5 23.6 -16.4 -17.4
2 -72.9 15.7 7.1 5.2 6.4
3 -104.4 12.4 3.7 12.8 21.1
 
Means
1 2 3 4
1 5.006 3.428 1.462 0.246
2 5.936 2.770 4.260 1.326
3 6.588 2.974 5.552 2.026
 
Stats
1 147.0
2 143.8
3 20.0
4 0.0
5 -13.1
6 -10.9
7 -8.9
8 -10.0
9 50.0
10 50.0
11 50.0
12 150.0
 
Membership
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
 
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
 
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2
 
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
2 2 2 2 2 2 2 2 2 2 3 2 2 2 2 2 2 2 2 2
 
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
2 2 2 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
 
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
2 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
 
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
 
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
3 3 2 3 3 3 3 3 3 3 3 3 3 3 3 3
 
148 149 150
3 3 3
 
Table
1 2 3
1 50 0 0
2 0 48 2
3 0 1 49
 
Prob
1 2 3
1 1.000 0.000 0.000
2 1.000 0.000 0.000
3 1.000 0.000 0.000
4 1.000 0.000 0.000
5 1.000 0.000 0.000
6 1.000 0.000 0.000
7 1.000 0.000 0.000
8 1.000 0.000 0.000
9 1.000 0.000 0.000
10 1.000 0.000 0.000
11 1.000 0.000 0.000
12 1.000 0.000 0.000
13 1.000 0.000 0.000
14 1.000 0.000 0.000
15 1.000 0.000 0.000
16 1.000 0.000 0.000
17 1.000 0.000 0.000
18 1.000 0.000 0.000
19 1.000 0.000 0.000
20 1.000 0.000 0.000
21 1.000 0.000 0.000
22 1.000 0.000 0.000
23 1.000 0.000 0.000
24 1.000 0.000 0.000
25 1.000 0.000 0.000
26 1.000 0.000 0.000
27 1.000 0.000 0.000
28 1.000 0.000 0.000
29 1.000 0.000 0.000
30 1.000 0.000 0.000
31 1.000 0.000 0.000
32 1.000 0.000 0.000
33 1.000 0.000 0.000
34 1.000 0.000 0.000
35 1.000 0.000 0.000
36 1.000 0.000 0.000
37 1.000 0.000 0.000
38 1.000 0.000 0.000
39 1.000 0.000 0.000
40 1.000 0.000 0.000
41 1.000 0.000 0.000
42 1.000 0.000 0.000
43 1.000 0.000 0.000
44 1.000 0.000 0.000
45 1.000 0.000 0.000
46 1.000 0.000 0.000
47 1.000 0.000 0.000
48 1.000 0.000 0.000
49 1.000 0.000 0.000
50 1.000 0.000 0.000
51 0.000 1.000 0.000
52 0.000 1.000 0.000
53 0.000 0.998 0.002
54 0.000 0.997 0.003
55 0.000 0.997 0.003
56 0.000 0.989 0.011
57 0.000 0.995 0.005
58 0.000 1.000 0.000
59 0.000 1.000 0.000
60 0.000 0.994 0.006
61 0.000 1.000 0.000
62 0.000 0.999 0.001
63 0.000 1.000 0.000
64 0.000 0.988 0.012
65 0.000 1.000 0.000
66 0.000 1.000 0.000
67 0.000 0.973 0.027
68 0.000 1.000 0.000
69 0.000 0.813 0.187
70 0.000 1.000 0.000
71 0.000 0.336 0.664
72 0.000 1.000 0.000
73 0.000 0.699 0.301
74 0.000 0.972 0.028
75 0.000 1.000 0.000
76 0.000 1.000 0.000
77 0.000 0.998 0.002
78 0.000 0.861 0.139
79 0.000 0.992 0.008
80 0.000 1.000 0.000
81 0.000 1.000 0.000
82 0.000 1.000 0.000
83 0.000 1.000 0.000
84 0.000 0.154 0.846
85 0.000 0.943 0.057
86 0.000 0.996 0.004
87 0.000 0.999 0.001
88 0.000 0.999 0.001
89 0.000 1.000 0.000
90 0.000 0.999 0.001
91 0.000 0.981 0.019
92 0.000 0.997 0.003
93 0.000 1.000 0.000
94 0.000 1.000 0.000
95 0.000 0.999 0.001
96 0.000 1.000 0.000
97 0.000 1.000 0.000
98 0.000 1.000 0.000
99 0.000 1.000 0.000
100 0.000 1.000 0.000
101 0.000 0.000 1.000
102 0.000 0.000 1.000
103 0.000 0.000 1.000
104 0.000 0.006 0.994
105 0.000 0.000 1.000
106 0.000 0.000 1.000
107 0.000 0.004 0.996
108 0.000 0.000 1.000
109 0.000 0.000 1.000
110 0.000 0.000 1.000
111 0.000 0.006 0.994
112 0.000 0.001 0.999
113 0.000 0.000 1.000
114 0.000 0.000 1.000
115 0.000 0.000 1.000
116 0.000 0.000 1.000
117 0.000 0.033 0.967
118 0.000 0.000 1.000
119 0.000 0.000 1.000
120 0.000 0.041 0.959
121 0.000 0.000 1.000
122 0.000 0.000 1.000
123 0.000 0.000 1.000
124 0.000 0.028 0.972
125 0.000 0.001 0.999
126 0.000 0.007 0.993
127 0.000 0.057 0.943
128 0.000 0.151 0.849
129 0.000 0.000 1.000
130 0.000 0.020 0.980
131 0.000 0.000 1.000
132 0.000 0.009 0.991
133 0.000 0.000 1.000
134 0.000 0.605 0.395
135 0.000 0.000 1.000
136 0.000 0.000 1.000
137 0.000 0.000 1.000
138 0.000 0.050 0.950
139 0.000 0.141 0.859
140 0.000 0.000 1.000
141 0.000 0.000 1.000
142 0.000 0.000 1.000
143 0.000 0.000 1.000
144 0.000 0.000 1.000
145 0.000 0.000 1.000
146 0.000 0.000 1.000
147 0.000 0.000 1.000
148 0.000 0.001 0.999
149 0.000 0.000 1.000
150 0.000 0.061 0.939
 
D2
1 2 3
1 0.0 323.1 706.1
2 103.2 0.0 17.9
3 168.8 13.8 0.0
 
 
Covariance
1 2 3 4
1 0.1242 0.0992 0.0164 0.0103
2 0.0992 0.1437 0.0117 0.0093
3 0.0164 0.0117 0.0302 0.0061
4 0.0103 0.0093 0.0061 0.0111
 
nrmiss = 0
Warning Errors
IMSLS_BAD_OBS_1
In call #, row # of the data matrix, “x”, has group number = #. The group number must be an integer between 1.0 and “n_groups” = #, inclusively. This observation will be ignored.
IMSLS_BAD_OBS_2
The leaving out one method is specified but this observation does not have a valid group number (Its group number is #.). This observation (row #) is ignored.
IMSLS_BAD_OBS_3
The leaving out one method is specified but this observation does not have a valid weight or it does not have a valid frequency. This observation (row #) is ignored.
IMSLS_COV_SINGULAR_3
The group # covariance matrix is singular. “stats[1]” cannot be computed. “stats[1]” and “stats[3]” are set to the missing value code (NaN).
Fatal Errors
IMSLS_BAD_IDO_1
ido” = #. Initial allocations must be performed by making a call to discriminant_analysis with “ido” = 1.
IMSLS_BAD_IDO_2
ido” = #. A new analysis may not begin until the previous analysis is terminated with “ido” equal to 5 or 6.
IMSLS_COV_SINGULAR_1
The variance-covariance matrix for population number # is singular. The computations cannot continue.
IMSLS_COV_SINGULAR_2
The pooled variance-covariance matrix is singular. The computations cannot continue.
IMSLS_COV_SINGULAR_4
A variance-covariance matrix is singular. The index of the first zero element is equal to #.