10  Composite Scores

Clinicians use composite scores whenever they can because they tend to be more reliable and valid than single scores. How much more reliable is a composite score than a single score? It, of course, depends. First, the reliability coefficients of all of the scores that make up the composite score matter. Second, the correlations among the components of the composite matter. The more reliable and correlated the components, the more reliable the composite.

A composite variable is the (possibly weighted) sum of two or more variables.

As discussed previously, it is quite possible for different scores from the same test to have different reliability coefficients. Scores from the same test tend to have similar reliability coefficients, though it is quite possible for differences in reliability to be large. In a well designed test, such cases are rare. If we can assume that the test is well designed and that test score reliability coefficients are within a fairly narrow range, we can assume that the classical reliability coefficient is a good estimate of the reliability of all scores from a particular test. To the degree that such assumptions are incorrect, the following equations will be less accurate.

Before we can discuss the reliability of composites, we must cover more basic statistics as they apply to composite scores. I will present this material in three ways. First, I will show the equations in standard notation. Adjacent to this, I will show the same equations in matrix notation.1 Then I will walk through the calculations using R.

1 Why bother with matrices? It does seem to be an unnecessary complication at first. However, many things become clearer and simpler with matrices, which I hope to illustrate. Furthermore, R was designed to work elegantly with vectors and matrices.

10.1 The Mean of the Sum Is the Sum of the Means

This section is going to make a simple idea look complicated. If you get lost, this is what I am trying to say:

If we create a new random variable by adding a bunch of random variables together, the mean of that new variable is found by adding together the means of all the variables we started with.

I’m sorry for what comes next, but the work we put into it will pay off later. Okay, now let’s make that simple idea formal and hard to understand:

We can start with the example of two variables: X_1 and X_2. The sum of these variables, which we will call X_S, has a mean, which is the sum of the means of X_1 and X_2. That is, \mu_{S}=\mu_{1}+\mu_{2}.

What if we have three variables? or four? or five? It would be tedious to illustrate each case one by one. We need a way of talking about the sum of a bunch of random variables but without worrying about how many variables there are. Here we go:

10.1.1 Calculating a Sum

Suppose k is a positive integer greater than 1. So if there are k random variables, the notation for the set of all them is \{X_1,...,X_k\}. However, it is even more compact to use matrix notation such that \mathbf{X}=\{X_1,...,X_k\}.

Now, \mathbf{X} is a set of random variables in their entirety, without referencing any particular values those variables might generate. A set of particular values of these variables would be shown as \mathbf{x} or \{x_1,...,x_k\}. In regular notation, the sum of these particular values would be:

x_S=\sum_{i=1}^{k}{x_i}

Symbol Meaning
x_S The sum of all k scores in \{x_1,...,x_k\}
x_i A particular score generated by variable X_i
k The number of variables in \{X_1,...,X_k\}, (k \in \mathbb{N}_1)

The same formula is more compact in matrix notation:

x_S=\mathbf{x'1}

Where

Symbol Meaning
\mathbf{x} A k \times 1 vector of scores \{x_1,x_2,...,x_k\}
\mathbf{1} A k \times 1 vector of ones \{1_1,1_2,...,1_k\}

The \mathbf{1} symbol may be a bit confusing. It is a column of ones that has the same length (number of elements) as \mathbf{x}. Suppose that \mathbf{x} has a length of three. In this case:

\mathbf{1}_3=\begin{bmatrix}1\\ 1\\ 1 \end{bmatrix}

Also, \mathbf{x'}, is \mathbf{x} transposed.

To transpose means to make all columns of a matrix into rows (or all rows into columns).

Transposition is noted with a prime symbol (\mathbf{^\prime}). If

\mathbf{A}= \begin{bmatrix} 1 & 2 & 3\\ 4 & 5 & 6\\ \end{bmatrix} then

\mathbf{A'}= \begin{bmatrix} 1 & 4\\ 2 & 5\\ 3 & 6\\ \end{bmatrix}

A column of 3 ones:

\mathbf{1}_3=\begin{bmatrix}1\\1\\1\end{bmatrix}

Transposed, a column of 2 ones is a row of 2 ones.

\mathbf{{1'}}_2=\begin{bmatrix}1&1\end{bmatrix}

Typically, the number of ones is implied such that the length of the column or row will be compatible with the adjacent matrix. For example, post-multiplying by a vector ones will create a vector of row totals:

\begin{align*} \mathbf{A1}&=\begin{bmatrix} 1 & 2 & 3\\ 4 & 5 & 6\\ \end{bmatrix}\begin{bmatrix}1\\1\\1\end{bmatrix}\\ &=\begin{bmatrix}1+2+3\\4+5+6\end{bmatrix}\\ &=\begin{bmatrix}6\\15\end{bmatrix} \end{align*}

Pre-multiplying by a vector of ones will create column totals:

\begin{align*} \mathbf{1'A}&=\begin{bmatrix}1\\1\end{bmatrix}'\begin{bmatrix} 1 & 2 & 3\\ 4 & 5 & 6\\ \end{bmatrix}\\ &=\begin{bmatrix}1&1\end{bmatrix}\begin{bmatrix} 1 & 2 & 3\\ 4 & 5 & 6\\ \end{bmatrix}\\ &=\begin{bmatrix}1+4 & 2+5 & 3+6\end{bmatrix}\\&=\begin{bmatrix}5 & 7 & 9\end{bmatrix} \end{align*}

To create a sum of the entire matrix, multiply by \mathbf{1} on both sides:

\mathbf{1}'\mathbf{A1}=21

Therefore, \mathbf{x}' is a row vector. A row vector multiplied by a column vector is the sum of the product of each analogous element in the pair of vectors. Thus,

\begin{align*} \mathbf{x'1}&=\begin{bmatrix} x_1\\ x_2\\ x_3 \end{bmatrix}' \begin{bmatrix}1\\ 1\\ 1 \end{bmatrix} \\ &=\begin{bmatrix} x_1 & x_2 & x_3\end{bmatrix} \begin{bmatrix}1\\ 1\\ 1\end{bmatrix}\\ &=x_1 \times 1 + x_2 \times 1 + x_3 \times 1\\ &= x_1 + x_2 + x_3 \end{align*}

Let’s do some calculations in R with a particular example. Suppose that there are three variables: \mathbf{X}=\{X_1, X_2, X_3\}. In R, we will create a vector of the names of variables in \mathbf{X}:

Xnames <- c("X1","X2","X3")

Now suppose that there are three particular scores: \mathbf{x}=\{100,120,118\}

# x = vector of particular scores from variables X1, X2, X3
x <- c(110,120,118)

# The `names` function returns or sets the names of vector elements.
# Applying Xnames to x (to make output easier to read)
names(x) <- Xnames 

Alternatively, names and values can be set in a single line:

x <- c(X1 = 110, X2 = 120, X3 = 118)

For reasons of clarity and readability, I prefer this approach for name assignments that I only need to perform once. However, when I need to apply the same names to different objects repeated, I use the names function to apply a vector of names.

The sum of these three scores can be calculated in a variety of ways. Here is the easiest:

# x_S = The sum of scores x1, x2, and x3
x_S <- sum(x)

However, if we want to be matrix algebra masochists (and, apparently, at least one of us does!), we could do this:

# A vector of ones the same length as x
ones <- rep(1, length(x))

# Notes: 
# The rep function creates vectors of repeated elements. 
# For example, rep(5,3) is the same as c(5,5,5).
# 
# The length function returns the number of elements in a vector. 
# For example, length(c(3,3)) returns `2`.


# Calculating x_S with matrix algebra
x_S <- t(x) %*% ones

# Notes: 
# The t function transposes a vector or matrix.
# The operator %*% multiplies compatible matrices.

Either way that we calculate it, x_S = 348.

10.1.2 Calculating the Mean of a Sum

The mean of X_S is:

\mu_{S}=\sum_{i=1}^{k}{\mu_i}=\mathbf{\mu'1}

Symbol Meaning
\mu_S The mean of X_S
\mu_i The mean of X_i
\mathbf{\mu} A k \times 1 vector of means of the variables in \mathbf{X}

Suppose that the means of X_1, X_2, and X_3 are all 100.

# m = vector of means of X
m <- c(100,100,100)

Again, the mean of X_S (\mu_S) can be calculated in two ways:

# m_S = The mean of S
# The easy way
m_S <- sum(m)

# With matrix algebra
m_S <- t(m) %*% ones

Running this code, we can see that \mu_S = 300.

10.1.3 Calculating the Mean of a Weighted Sum

The mean of a weighted sum is the weighted sum of the means. That is, if

\begin{equation} x_S=\sum_{i=1}^{k}{x_i w_i}=\mathbf{x'w} \end{equation}

Where

then

\begin{equation} \mu_S=\sum_{i=1}^{k}{\mu_i w_i}=\mathbf{\mu'w} \end{equation}

Note that the calculation of X_S and \mu_S with matrix algebra is the same as it was with an equally weighted sum except that instead of post-multiplying by a vector of ones (\mathbf{x^\prime 1}), we post-multiply by a vector of weights (\mathbf{x^\prime w}). In truth, an equally weighted sum is a special case of a weighted sum in which \mathbf{w} consists entirely of ones.

Suppose that \mathbf{w} = \{0.5,1,2\}. That is, the weight for X_1 is 0.5, the weight for X_2 is 1, and the weight for X_3 is 2. We will continue to use the same values for \mathbf{x} and \mathbf{\mu} as before:

# w = The vector of weight for variables X1, X2, and X3
w = c(0.5, 1, 2)

# The easy way
x_S_weighted <- sum(x * w)
m_S_weighted <- sum(m * w)

# Notes:
# The multiplication operator * multiplies analogous elements 
# of vectors  and matrices. In the example, `x * w` is 
# c(110 * 0.5, 120 * 1, 118 * 2)

# With matrix algebra
x_S_weighted <- t(x) %*% w
m_S_weighted <- t(m) %*% w

Running the code shows that x_S = 411 and that \mu_S = 350.

10.2 The Variance of the Sum Is the Sum of the Covariance Matrix

Unfortunately, the notation for a covariance matrix is a bold capital sigma \mathbf{\Sigma}, which is easily confused with the summation symbol, which is generally larger and not bold: \sum.

If variables are uncorrelated, the variance of their sum is the sum of their variances. However, this is not true when variables are substantially correlated. The formula for the variance of a sum looks more complex than it is. It is just the sum of the covariance matrix.

\sigma_{X_S}^2=\sum_{i=1}^{k}{\sum_{j=1}^{k}{\sigma_{ij}}}=\mathbf{1'\Sigma 1} \tag{10.1}

Symbol Meaning
\sigma_{X_S}^2 The variance of X_S
\sigma_{ij} The covariance between X_i and X_j (\sigma_{ij}=\sigma_i^2 if i=j)
\mathbf{\Sigma} The k \times k covariance matrix of all the variables in \mathbf{X}

The symbol for a sample correlation is the Roman lowercase r, and a matrix of such correlations is an uppercase \mathbf{R}. Therefore, the population correlation coefficient is a Greek lowercase rho: \rho. This, unfortunately means that a matrix of correlations should be an uppercase rho: \mathbf{P}. Somehow, statisticians are okay with \rho looking a lot like an italicized Roman letter p. However, using an uppercase rho (\mathbf{P}) for a correlation matrix is too weird even for statisticians! You know, hobgoblins of little minds and all…

Suppose that the standard deviations of X_1, X_2, and X_3 are all 15. Thus, \sigma=\{15,15,15\}. The correlations among the three variables are shown in matrix \mathbf{R}:

\mathbf{R} = \begin{bmatrix} 1 & 0.5 & 0.6\\ 0.5 & 1 & 0.7\\ 0.6 & 0.7 & 1 \end{bmatrix}

To create this matrix in R:

# R = correlation matrix of variables in X
R <- matrix(c(1, 0.5, 0.6, 
              0.5, 1, 0.7,  
              0.6, 0.7, 1),
    nrow = 3,
    ncol = 3,
    byrow = TRUE)

R
     [,1] [,2] [,3]
[1,]  1.0  0.5  0.6
[2,]  0.5  1.0  0.7
[3,]  0.6  0.7  1.0

The covariance matrix \mathbf{\Sigma} can be computed from the correlation matrix and the standard deviations like so:

\sigma_{ij} = \sigma_{i} \sigma_{j} \rho_{ij}

Symbol Meaning
\sigma_{ij} The covariance between X_i and X_j
\rho_{ij} The correlation between X_i and X_j
\sigma_{i} The standard deviation of variable X_i
\sigma_{j} The standard deviation of variable X_j

Unfortunately, computing a covariance matrix like this in a computer program is inelegant because we have to make use of looping:

# R = Correlation matrix of variables in X
R <- matrix(c(1,0.5,0.6,
              0.5,1,0.7,
              0.6,0.7,1), nrow = 3)
rownames(R) <- colnames(R) <- Xnames #Apply names

# s = The standard deviations of variables in X
s <- c(15,15,15)

# k = The number of variables
k <- length(s)

# CM = Covariance Matrix
# Initialize k by k matrix of zeroes
CM <- matrix(0, k, k)
rownames(CM) <- colnames(CM) <- Xnames
for (i in seq(1, k)) {
  for (j in seq(1, k)) {
    CM[i, j] = s[i] * s[j] * R[i, j]
  }
}

CM
      X1    X2    X3
X1 225.0 112.5 135.0
X2 112.5 225.0 157.5
X3 135.0 157.5 225.0

The \mathtt{diag} function has three purposes. First, it can extract the diagonal vector from a matrix: A_{kk} = \begin{bmatrix} a_{11} & a_{12} & \cdots & a_{1k} \\ a_{21} & a_{22} & \cdots & a_{2k} \\ \vdots & \vdots & \ddots & \vdots \\ a_{k1} & a_{k2} & \cdots & a_{kk} \end{bmatrix} Then \mathtt{diag}(\mathbf{A}) = \{a_{11},a_{22},...,a_{kk}\} Second, the diag function inserts a vector into the the diagonal of a k \times k matrix of zeros: \mathtt{diag}(\mathbf{a}) = \begin{bmatrix} a_{1} & 0 & \cdots & 0 \\ 0 & a_{2} & \cdots & 0 \\ \vdots & \vdots & \ddots & \vdots \\ 0 & 0 & \cdots & a_{k} \end{bmatrix} Third, the diag function converts integer k into a k \times k identity matrix: \mathtt{diag}(k) = \begin{bmatrix} 1 & 0 & \cdots & 0 \\ 0 & 1 & \cdots & 0 \\ \vdots & \vdots & \ddots & \vdots \\ 0 & 0 & \cdots & 1 \end{bmatrix}

To calculate the covariance matrix in matrix notation, we can make use of the \mathtt{diag} function.

\begin{align*} \mathbf{\Sigma}&=\mathtt{diag}(\mathbf{\sigma}) \mathbf{R}\, \mathtt{diag}(\mathbf{\sigma})\\ &=\begin{bmatrix} \sigma_{1} & 0 & \cdots & 0 \\ 0 & \sigma_{2} & \cdots & 0 \\ \vdots & \vdots & \ddots & \vdots \\ 0 & 0 & \cdots & \sigma_{k} \end{bmatrix} \begin{bmatrix} 1 & \rho_{12} & \cdots & \rho_{1k} \\ \rho_{21} & 1 & \cdots & \rho_{2k} \\ \vdots & \vdots & \ddots & \vdots \\ \rho_{k1} & \rho_{k2} & \cdots & 1 \end{bmatrix} \begin{bmatrix} \sigma_{1} & 0 & \cdots & 0 \\ 0 & \sigma_{2} & \cdots & 0 \\ \vdots & \vdots & \ddots & \vdots \\ 0 & 0 & \cdots & \sigma_{k} \end{bmatrix}\\ &= \begin{bmatrix} \sigma_{1}^2 & \sigma_{1}\sigma_{2}\rho_{12} & \cdots & \sigma_{1}\sigma_{k}\rho_{1k} \\ \sigma_{2}\sigma_{1}\rho_{21} & \sigma_{2}^2 & \cdots & \sigma_{2}\sigma_{k}\rho_{2k} \\ \vdots & \vdots & \ddots & \vdots \\ \sigma_{k}\sigma_{1}\rho_{k1} & \sigma_{k}\sigma_{2}\rho_{k2} & \cdots & \sigma_{k}^2 \end{bmatrix}\\ &= \begin{bmatrix} \sigma_{1}^2 & \sigma_{12} & \cdots & \sigma_{1k} \\ \sigma_{21} & \sigma_{2}^2 & \cdots & \sigma_{2k} \\ \vdots & \vdots & \ddots & \vdots \\ \sigma_{k1} & \sigma_{k2} & \cdots & \sigma_{k}^2 \end{bmatrix} \end{align*}

Symbol Meaning
\mathbf{\Sigma} The covariance matrix of variables in \mathbf{X}
\mathbf{\sigma} The standard deviations of variables in \mathbf{X}
\mathbf{R} The correlation matrix of variables in \mathbf{X}

So this is where matrix algebra starts to shine. We do not need to initialize the variable that contains the covariance matrix, or calculate k, or do any looping.

# CM = Covariance matrix of variables in X
CM <- diag(s) %*% R %*% diag(s)

Beautiful!

Running the code, we get: \mathbf{\Sigma}=\begin{bmatrix} 225 & 112.5 & 135\\ 112.5 & 225 & 157.5\\ 135 & 157.5 & 225 \end{bmatrix}

To calculate the variance of X_S if it is an unweighted sum we apply Equation 10.1:

Here we see that \sigma_X^2=1485

10.3 Calculating the Variance of a Weighted Sum

If X_S is a weighted sum, its variance is the weighted sum of the covariance matrix.

\sigma_S^2=\sum_{i=1}^{k}{\sum_{j=1}^{k}{w_i w_j \sigma_{ij}}}=\mathbf{w'\Sigma w} \tag{10.2}

Continuing with the same variables in our example, we see that things are starting to become clumsy and ugly without matrix algebra:

# First we initialize var_S as 0
var_S_weighted <- 0
# Now we loop through k rows and k columns of CM
for (i in seq(1, k)) {
  for (j in seq(1, k)) {
    var_S_weighted <- var_S_weighted + w[i] * w[j] * CM[i, j]
  }
}

With matrix algebra, this all happens with a single line of code:

var_S_weighted <- t(w) %*% CM %*% w

If we don’t need to know the covariance matrix, we can skip its calculation:

var_S_weighted <- t(w * s) %*% R %*% (w * s)

All three methods give the same answer: \sigma_X^2 = 2193.75

10.4 Calculating a Composite Score

We now have all of the information needed to make a composite score. First we will make an unweighted composite.

\begin{equation} C = \frac{x_S-\mu_S}{\sigma_{X_S}}\sigma_C + \mu_C (\#eq:Composite) \end{equation}

Symbol Meaning
C The composite variable C
x_S The sum of all k scores in \{x_1,...,x_k\}
\sigma_{X_S} The standard deviation of X_S
\sigma_C The standard deviation of C
\mu_C The mean of C

Continuing with our example, suppose that \mu_C=100 and \sigma_C=15.

# m_C = Composite mean
m_C <- 100
# s_C = Composite standard deviation
s_C <- 15
# C = The composite score
C <- ((x_S - m_S) / sqrt(var_S)) * s_C + m_C

C=119

10.4.1 Calculating a Weighted Composite Score

In matrix notation, an unweighted composite score is calculated like so:

C=\mathbf{\frac{1'(x-\mu_x)}{\sqrt{1'\Sigma 1}}}\sigma_C+\mu_C Replacing each vector of ones \mathbf{1} with a weight vector \mathbf{w} gives us the formula for computing a weighted composite score:

C_w=\mathbf{\frac{w'(x-\mu_x)}{\sqrt{w'\Sigma w}}}\sigma_C+\mu_C

In clinical practice, the most common kind of composite score is an equally weighted composite consisting of scores with the same mean and standard deviation. Sometimes scores are weighted by the degree to which they correlate with the construct the composite is intended to measure. Other weighting schemes are also possible. In most cases, it makes sense to first convert all scores to z-scores and then weight the z-scores. Failing to convert the scores to a common metric such as z-scores will result in an implicit weighting by standard deviations. That is, the score with the largest standard deviation will have the most weight in the composite score. Converting to z-scores first will equalize the each score’s influence on the composite score. We can convert all the scores in \mathbf{x} to z-scores like so:

\mathbf{z} = \frac{\mathbf{x}-\mathbf{\mu}}{\mathbf{\sigma}}

The nice thing about z-scores is that their means are zeros, their standard deviations are ones, and their covariances are correlations. Thus, the formula for a weighted composite score consisting of z-scores is fairly simple, especially if the composite score is a z-score itself:

C = \frac{\mathbf{w^\prime z}}{\sqrt{\mathbf{w^\prime Rw}}}\sigma_C+\mu_C

Continuing with our example, computing a composite score with X_1=110, X_2=120, and X_3=118:

# C = The composite score
C <- (t(w) %*% (x - m) / sqrt(t(w) %*% CM %*% w)) * 15  + 100

# With index scores, we round to the nearest integer
C <- round(C)

# Notes:
# The round function rounds to the nearest integer by default,
# but you can round to any number of digits you wish. For example, 
# rounding to 2 significant digits (i.e., the hundredths place), 
# would be round(x,2).

Here we see, that the weighted composite score C = 120. If we had wanted an equally weighted composite score, the w vector would be set to equal ones. If we had done so, C would have been 119 instead of 120.

10.5 The Reliability Coefficient of a Composite

Calculating the reliability coefficient of a composite score is much easier than it might appear at first. Remember that reliability is the ratio of a score’s true score variance to its total variance:

r_{XX} = \frac{\sigma_T^2}{\sigma_X^2}

The variance of a composite score is the sum of the covariance matrix of the composite’s component scores.

\sigma_X^2=\mathbf{1}'\begin{bmatrix} \sigma_{1}^2 & \sigma_{12} & \cdots & \sigma_{1k} \\ \sigma_{21} & \sigma_{2}^2 & \cdots & \sigma_{2 k} \\ \vdots & \vdots & \ddots & \vdots \\ \sigma_{k1} & \sigma_{k2} & \cdots & \sigma_{k}^2 \end{bmatrix}\mathbf{1}

The covariance matrix of the component true scores is exactly the same as the covariance matrix of the component observed scores, except that the variances on the diagonal are multiplied by the reliability coefficients of each of the component scores like so:

\sigma_T^2=\mathbf{1}'\begin{bmatrix} {\color{firebrick}r_{11}}\sigma_{1}^2 & \sigma_{12} & \cdots & \sigma_{1k} \\ \sigma_{21} & {\color{firebrick}r_{22}}\sigma_{2}^2 & \cdots & \sigma_{2 k} \\ \vdots & \vdots & \ddots & \vdots \\ \sigma_{k1} & \sigma_{k2} & \cdots & {\color{firebrick}r_{kk}}\sigma_{k}^2 \end{bmatrix}\mathbf{1}

# r_XX = Reliability coefficients for X1, X2, and X3
r_XX <- c(0.88,0.80,0.76)

# CM_T = Covariance matrix of true scores
CM_T <- CM

# Replace diagonal with true score variances
diag(CM_T) <- diag(CM) * r_XX

# r_C = Reliability coefficient of composite score
r_C <- sum(CM_T) / sum(CM)

The reliability coefficient of the unweighted composite is 0.92.

For a weighted composite, the reliability is calculated by relplacing each vector of ones \mathbf{1} with a weight vector \mathbf{w}:

\rho_{XX}=\frac{\sigma_T^2} {\sigma_X^2} =\frac{\mathbf{w}^{\prime} \begin{bmatrix} {\color{firebrick}r_{11}}\sigma_{1}^2 & \sigma_{12} & \cdots & \sigma_{1k} \\ \sigma_{21} & {\color{firebrick}r_{22}}\sigma_{2}^2 & \cdots & \sigma_{2 k} \\ \vdots & \vdots & \ddots & \vdots \\ \sigma_{k1} & \sigma_{k2} & \cdots & {\color{firebrick}r_{kk}}\sigma_{k}^2 \end{bmatrix} \mathbf{w}} {\mathbf{w}^{\prime} \begin{bmatrix} \sigma_{1}^2 & \sigma_{12} & \cdots & \sigma_{1k} \\ \sigma_{21} & \sigma_{2}^2 & \cdots & \sigma_{2 k} \\ \vdots & \vdots & \ddots & \vdots \\ \sigma_{k1} & \sigma_{k2} & \cdots & \sigma_{k}^2 \end{bmatrix}\mathbf{w}}

# Reliability coefficient of the weighted composite
r_C_w <- t(w) %*% CM_T %*% w / t(w) %*% CM %*% w

The reliability coefficient of the weighted composite is 0.88.

10.6 Composite Scores and Their Correlations

If the population correlations among all of the components are known, it is possible to calculate the correlations among composite scores made from these components. Such correlations can be used in many practical applications, including in prediction models and in the evaluation of difference scores.

Suppose that Composite A is calculated from the sum of two component tests, A_1 and A_2. Composite B is calculated from the sum of B_1 and B_2. Suppose that the correlation matrix for the four components is:

\mathbf{R} = \begin{array}{r|cccc} & \color{royalblue}{A_1} & \color{royalblue}{A_2} & \color{firebrick}{B_1} & \color{firebrick}{B_2}\\ \hline \color{royalblue}{A_1} & \color{royalblue}{1} & \color{royalblue}{.30} & \color{purple}{.35} & \color{purple}{.40}\\ \color{royalblue}{A_2} & \color{royalblue}{.30} & \color{royalblue}{1} & \color{purple}{.42} & \color{purple}{.48}\\ \color{firebrick}{B_1} & \color{purple}{.35} & \color{purple}{.42} & \color{firebrick}{1} & \color{firebrick}{.56}\\ \color{firebrick}{B_2} & \color{purple}{.40} & \color{purple}{.48} & \color{firebrick}{.56} & \color{firebrick}{1} \end{array}

# Make correlation matrix R
R <- matrix(c(1, .30, .35, .40,
              .30, 1, .42, .48,
              .35, .42, 1, .56,
              .40, .48, .56, 1),
            nrow = 4,
            ncol = 4)

# Display R
R
     [,1] [,2] [,3] [,4]
[1,] 1.00 0.30 0.35 0.40
[2,] 0.30 1.00 0.42 0.48
[3,] 0.35 0.42 1.00 0.56
[4,] 0.40 0.48 0.56 1.00

The correlation between Composite A and Composite B is calculating by adding up the numbers is all three shaded regions of the correlation matrix and then dividing the sum of “between” correlations in purple by the geometric mean of the sums from the “within” correlations in the blue and red regions in the correlation matrix \mathbf{R} like so:

r_{AB}=\dfrac{\color{purple}{\text{Sum of Correlations between A and B}}}{\sqrt{\color{royalblue}{\text{Sum of Correlations Within A}}\times\color{firebrick}{{\text{Sum of Correlations Within B}}}}}

To calculate these sums using matrix algebra, we first construct a “weight matrix” \mathbf{W} that tells us which tests are in which composite. The 1s in the first two rows of column 1 tell us that tests A_1 and A_2 belong to composite A. Likewise, the 1s in the last two rows of column 2 tell us that B_1 and B_2 belong to composite B.

\mathbf{W}= \begin{array}{r|cc} & \color{royalblue}{A} & \color{firebrick}{B}\\ \hline \color{royalblue}{A_1} & \color{royalblue}{1} & 0\\ \color{royalblue}{A_2} & \color{royalblue}{1} & 0\\ \color{firebrick}{B_1} & 0 & \color{firebrick}{1}\\ \color{firebrick}{B_2} & 0 & \color{firebrick}{1} \end{array}

Here is one way to make the weight matrix in R:

# Make a 4 by 2 matrix of 0s
W <- matrix(0, nrow = 4, ncol = 2)

# Assign 1s to rows 1 and 2 to column 1
W[1:2,1] <- 1
# Assign 1s to rows 3 and 4 to column 2
W[3:4,2] <- 1

# Display W
W
     [,1] [,2]
[1,]    1    0
[2,]    1    0
[3,]    0    1
[4,]    0    1

The covariance matrix \mathbf{\Sigma_{AB}} is calculated by pre- and post-mulitplying \mathbf{R} by the wieght matrix .

\begin{aligned}\mathbf{\Sigma_{AB}} &= \mathbf{W'RW}\\[2ex] &=\left[\begin{array}{cc} \color{royalblue}{1} & 0\\ \color{royalblue}{1} & 0\\ 0 & \color{firebrick}{1}\\ 0 & \color{firebrick}{1} \end{array}\right]'\left[\begin{array}{cccc} \color{royalblue}{1} & \color{royalblue}{.30} & \color{purple}{.35} & \color{purple}{.40}\\ \color{royalblue}{.30} & \color{royalblue}{1} & \color{purple}{.42} & \color{purple}{.48}\\ \color{purple}{.35} & \color{purple}{.42} & \color{firebrick}{1} & \color{firebrick}{.56}\\ \color{purple}{.40} & \color{purple}{.48} & \color{firebrick}{.56} & \color{firebrick}{1} \end{array}\right]\left[\begin{array}{cc} \color{royalblue}{1} & 0\\ \color{royalblue}{1} & 0\\ 0 & \color{firebrick}{1}\\ 0 & \color{firebrick}{1} \end{array}\right]\\[2ex] &=\begin{array}{r|cc} & \color{royalblue}{A} & \color{firebrick}{B}\\ \hline \color{royalblue}{A} & \color{royalblue}{1 + .30 + .30 + 1} & \color{purple}{.35 + .42 + .40 + .48}\\ \color{firebrick}{B} & \color{purple}{.35 + .40 + .42 + .48} & \color{firebrick}{1 + .56 + .56 + 1} \end{array}\\[2ex] &=\begin{array}{r|cc} & \color{royalblue}{A} & \color{firebrick}{B}\\ \hline \color{royalblue}{A} & \color{royalblue}{2.60} & \color{purple}{1.65}\\ \color{firebrick}{B} & \color{purple}{1.65} & \color{firebrick}{3.12} \end{array} \end{aligned}

# Covariance matrix of composites A and B
Sigma_AB <- t(W) %*% R %*% W

# Display Sigma_AB
Sigma_AB
     [,1] [,2]
[1,] 2.60 1.65
[2,] 1.65 3.12

Now we need to extract the variance diagonal from the covariance matrix so that we can use them to convert the covariance matrix to a correlation matrix. The variances are put on a diagonal matrix, and then taking the square root converts the variances to standard deviations in matrix \mathbf{\sigma}.

\begin{aligned} \mathbf{\sigma} &=\mathtt{diag}(\mathtt{diag}(\mathbf{\Sigma_{AB}}))^{\frac{1}{2}}\\ &=\mathtt{diag}\left( \mathtt{diag}\left({ \left[\begin{array}{cc} \color{royalblue}{2.60} & \color{purple}{1.65}\\ \color{purple}{1.65} & \color{firebrick}{3.12} \end{array}\right] }\right) \right)^{\frac{1}{2}}\\ &=\mathtt{diag}\left( \left[\begin{array}{c} \color{royalblue}{2.60}\\ \color{firebrick}{3.12} \end{array}\right] \right)^{\frac{1}{2}}\\ &=\left[\begin{array}{cc} \color{royalblue}{2.60} & 0\\ 0 & \color{firebrick}{3.12} \end{array}\right]^{\frac{1}{2}}\\ &=\left[\begin{array}{cc} \color{royalblue}{1.6125} & 0\\ 0 & \color{firebrick}{1.7664} \end{array}\right] \end{aligned}

# Standard deviations
sigma <- diag(diag(Sigma_AB)^(0.5))

# Display sigma
sigma
         [,1]     [,2]
[1,] 1.612452 0.000000
[2,] 0.000000 1.766352

Pre- and post-multiplying the covariance matrix \mathbf{\Sigma_{AB}} by the inverted standard devation matrix \mathbf{\sigma} to yield the correlations between composites A and B.

\begin{aligned} \mathbf{R_{AB}}&=\mathbf{\sigma}^{-1}\mathbf{\Sigma_{AB}}\mathbf{\sigma}^{-1}\\[2ex] &={\mathbf{\sigma}^{-1} \atop \left[\begin{array}{cc} \color{royalblue}{1.6125} & 0\\ 0 & \color{firebrick}{1.7664} \end{array}\right]^{-1}} {\mathbf{\Sigma_{AB}} \atop \left[\begin{array}{cc} \color{royalblue}{2.60} & \color{purple}{1.65}\\ \color{purple}{1.65} & \color{firebrick}{3.12} \end{array}\right]} {\mathbf{\sigma}^{-1} \atop \left[\begin{array}{cc} \color{royalblue}{1.6125} & 0\\ 0 & \color{firebrick}{1.7664} \end{array}\right]^{-1}}\\[1ex] &=\left[\begin{array}{cc} \color{royalblue}{.6202} & 0\\ 0 & \color{firebrick}{.5661} \end{array}\right] \left[\begin{array}{cc} \color{royalblue}{2.60} & \color{purple}{1.65}\\ \color{purple}{1.65} & \color{firebrick}{3.12} \end{array}\right] \left[\begin{array}{cc} \color{royalblue}{.6202} & 0\\ 0 & \color{firebrick}{.5661} \end{array}\right]\\[1ex] &=\left[\begin{array}{cc} \color{royalblue}{1} & \color{purple}{.58}\\ \color{purple}{.58} & \color{firebrick}{1} \end{array}\right] \end{aligned}

The solve function inverts a square matrix. Inverting a single number x gives its reciprocal. If you multiply the inverse of a number by the nunbe itself, you get 1, the identity for the multiplication operator. x^{-1}x=1, multiplying a matrix by its inverse creates an identity matrix (a matrix with ones on the diagonal and zeroes elsewhere):

\mathbf{A^{-1}A = I}

# Correlations between composites A and B
R_AB <- solve(sigma) %*% Sigma_AB %*% solve(sigma)
R_AB
          [,1]      [,2]
[1,] 1.0000000 0.5793219
[2,] 0.5793219 1.0000000

These calculations in R can be greatly simplified using the cov2cor function, which converts covariances to correlations:

# Correlation matrix of composites A and B
R_AB <- cov2cor(t(W) %*% R %*% W)

R_AB
          [,1]      [,2]
[1,] 1.0000000 0.5793219
[2,] 0.5793219 1.0000000