---
title: "Finding the nearest proper correlation matrix"
author: "Kevin Wright"
date: "`r Sys.Date()`"
bibliography: corrgram.bib
output: 
  rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Finding the nearest proper correlation matrix}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

Consider the following matrix, as might arise from calculating covariance based on pairwise-complete data.

```{r}
vv <- matrix(c(100.511, 159.266, 3.888, 59.964, 37.231, 32.944, 68.845,
               159.266, 277.723, 6.161, 95.017, 58.995, 52.203, 109.09, 3.888,
               6.161, 99.831, 2.32, 1.44, 1.274, 2.663, 59.964, 95.017, 2.32,
               35.774, 22.212, 19.655, 41.073, 37.231, 58.995, 1.44, 22.212,
               40.432, 12.203, 25.502, 32.944, 52.203, 1.274, 19.655, 12.203,
               10.798, 22.566, 68.845, 109.09, 2.663, 41.073, 25.502, 22.566,
               96.217), nrow=7, byrow=TRUE)
print(vv)
```

This is not a proper covariance matrix (it has a negative eigenvalue).
```{r}
eigen(vv)$values
```

If we attempt to use the `cov2cor()` function to convert the covariance matrix to a correlation matrix, we find the largest correlation values are slightly larger than 1.0.

```{r}
cc <- cov2cor(vv)
max(cc) # 1.000041
```

If this is passed to the `corrgram` function, it will issue a warning that the input data is not a correlation matrix and then calculate pairwise correlations of the columns, resulting in a non-sensical graph.

There are several packages with functions that can be used to force the correlation matrix to be an actual, positive-definite correlation matrix.  Two are given here.

## psych

```{r}
require(psych)
cc2 <- psych::cor.smooth(cc)
max(cc2)
```

## sfsmisc

```{r}
library(sfsmisc)
# nearcor uses 'identical' and says the matrix is not symmetric
isSymmetric(cc) # TRUE
identical(cc, t(cc)) # FALSE
# round slightly to make it symmetric
cc3 <- nearcor(round(cc,12))$cor
max(cc3)
```

After converting the matrix to a valid correlation matrix, an accurate corrgram can be created:
```{r, fig.width=6, fig.height=6, fig.align="center"}
require(corrgram)
corrgram(cc2, lower=panel.cor)
```

	
