Home / Tools / Correlation Matrix Calculator
Correlation Matrix Calculator
A correlation matrix answers one question for every pair of columns at once: when this one goes up, does that one tend to go up too, and how reliably? Paste a table with a header row and this calculator returns the whole matrix, colour coded, with the p-value and the sample size behind each cell. It uses Pearson or Spearman, handles gaps in the data by pairwise deletion and reports what that costs, and warns you about the multiple-testing trap that every large matrix sets.
I want to see how every column correlates with every other
One column per variable, one row per observation. Tabs, commas or spaces all work. A header row of names is picked up automatically. Write NA (or leave blank) for a missing value.
-
| Pair | r | n | p | Bonferroni | Holm | BH |
|---|
How these numbers are computed
✓ No data leaves your browser
✓ Verified against R's cor(), cor.test() and Hmisc::rcorr()
✓ Free, no sign-up
Reading a correlation matrix
Three numbers sit behind every cell, and they answer three different questions. Reading only the first one is how most correlation matrices get over-interpreted.
The correlation coefficient runs from -1 to +1. The sign is the direction: positive means they rise together, negative means one falls as the other rises. The magnitude is the strength, and 0 means no linear (Pearson) or monotonic (Spearman) relationship. An r of 0.6 is not "twice" an r of 0.3; square it instead, and 0.36 versus 0.09 of the variance is shared.
The p-value asks how easily a sample this correlated could arise if the two columns were truly unrelated. It is driven as much by n as by r: with n = 500 an r of 0.09 clears 0.05, and with n = 8 an r of 0.6 does not. So a small p is not evidence of a strong relationship, only of a detectable one.
With gaps in your data, each cell can rest on a different number of rows. A cell built on 7 rows and a cell built on 200 are not equally trustworthy even when both show r = 0.5. This is the number most correlation matrices never show you, which is why it is on every cell here.
Pairwise or listwise: what happens to your gaps
If any cell in your table is missing, the matrix has to decide which rows to keep. There are two common answers and they disagree on purpose.
Pairwise deletion (the default here, and cor(df, use = "pairwise.complete.obs") in R) lets every cell use every row where its own two columns are present. A pair of complete columns keeps all your rows; a pair involving a sparse column keeps fewer. That is why the n changes from cell to cell, and it is not a bug. Load the "clinic, with gaps" example above to watch it happen: the pairs range from 7 to 10 patients while the table has 12 rows.
Listwise deletion (use = "complete.obs", sometimes called complete-case analysis) throws away any row with a gap anywhere before computing anything. Every cell then rests on the same rows, so the cells are comparable and the matrix is guaranteed to be well behaved. The price shows up fast: in that same clinic example, listwise drops 7 of the 12 patients and computes every cell from the 5 that survive. Toggle "Missing" to Listwise and watch the n collapse.
The trade is real, and neither answer is free. Pairwise keeps information, but the cells no longer describe one common sample, and the matrix can come out non-positive-definite, which quietly breaks factor analysis, PCA, and anything else that inverts it. Listwise gives you one coherent sample and a matrix that always inverts, but it can discard most of your data when gaps are scattered across different columns, and it silently assumes the rows that vanished were missing at random. A good rule: pairwise when you are looking and describing, listwise (or, better, multiple imputation) when the matrix is feeding another model.
The trap: a big matrix runs a lot of tests
A correlation matrix is a significance-testing machine that never tells you how many tests it just ran.
With k columns, the matrix holds k(k-1)/2 unique pairs: 10 columns give 45 tests, 20 columns give 190. Each test gets its own p-value, and each has its own 5% chance of a false positive when nothing is going on. Run 45 independent tests at alpha = 0.05 on pure noise and you expect about 2.25 of them to come back "significant"; the chance of at least one is 1 - 0.9545, roughly 90%. Load the "10 noise columns" example above: those columns are independent random numbers with no relationship whatsoever, and the matrix still lights up.
The trap closes when you scan the matrix, spot the biggest r, and quote its p-value. That p-value assumes you nominated the pair in advance. You did not: you picked it because it was the most extreme of 45, which is precisely the selection the p-value cannot see. This is why a correlation matrix is a hypothesis-generating tool, not a hypothesis-testing one.
Bonferroni is the blunt fix: compare every p to alpha/m instead of alpha (with 45 tests, 0.05/45 = 0.0011), or equivalently multiply each p by m. It controls the chance of any false positive, makes no assumptions, and is easy to defend. It is also conservative, and with a large m it will bury real findings. Holm controls exactly the same thing while always being at least as powerful, so there is rarely a reason to prefer plain Bonferroni. If you would rather accept a known fraction of false positives among your discoveries than guard against a single one, Benjamini-Hochberg controls the false discovery rate and keeps far more power. The ranked-pairs mode above shows all three, side by side, on your data. For the full treatment, see the multiple testing correction calculator.
Which correlation, and which R function
| Choice | What it does | When it is the right call |
|---|---|---|
Pearsonmethod = "pearson" | Standardised covariance: measures how close the cloud sits to a straight line. | The default. Roughly linear relationships, continuous data, no single point dominating. Squaring r gives the shared variance directly. |
Spearmanmethod = "spearman" | Pearson applied to the ranks, so it measures monotonic association rather than a straight line. | Curved-but-consistent relationships, ordinal data, skewed data, or when one outlier is dragging Pearson around. Ranking discards the outlier's leverage. |
Pairwise deletionuse = "pairwise.complete.obs" | Each cell uses the rows where its own two columns are present, so n varies per cell. | Describing and exploring, when gaps are scattered and you want each pair to use everything it can. Not when the matrix feeds a model that inverts it. |
Listwise deletionuse = "complete.obs" | Drops every row with any gap first, so all cells share one sample and one n. | When cells must be comparable, or the matrix goes into PCA, factor analysis or regression. Costly when gaps are spread across many columns. |
| cor() | Returns the r matrix, and nothing else. | When you only want the coefficients. It gives you no p-values and no n, which is exactly how the two questions above get skipped. |
| Hmisc::rcorr() | Returns three matrices at once: $r, $n and $P. This tool reproduces all three. | The workhorse for a matrix with p-values. Note it requires more than 4 observations, always uses pairwise deletion, and applies the same t test to every cell. |
| cor.test() | One pair, in full: r, the test statistic, degrees of freedom, a confidence interval and an exact test where one exists. | Once the matrix has pointed at a pair worth taking seriously. It is the only one of the three that gives you a confidence interval, which is usually what you should be reporting. |
Questions people ask
What is a correlation matrix?
A square table holding the correlation between every pair of columns. With k columns it is k by k, carries a 1 down the diagonal (each column correlates perfectly with itself) and is symmetric, so the cell above the diagonal repeats the one below it. All the unique information lives in one triangle: k(k-1)/2 pairs. In R, cor(df) produces it.
Why does the n differ from cell to cell?
Pairwise deletion. Each cell uses only the rows where its own two columns are both present, so a pair of complete columns keeps more rows than a pair involving a sparse one. That is what use = "pairwise.complete.obs" and Hmisc::rcorr do. It means a matrix built from data with gaps is not built from one single sample, which is worth knowing before you compare one cell to another. Switch "Missing" to Listwise to give every cell the same n and see what it costs.
Can I trust the biggest correlation in the matrix?
Not on its p-value alone. You did not nominate that pair in advance; you picked it because it was the largest of k(k-1)/2, and its p-value has no way to know that. Check it against the Bonferroni or Holm column in the ranked-pairs mode, and if it still stands, confirm it on fresh data or with a pre-registered test. A correlation matrix is for generating hypotheses.
Does this match Hmisc::rcorr exactly?
Yes, and it is verified cell by cell against R over 42 test matrices: the r values, the pairwise n and the p-values all reproduce rcorr. For Pearson the p-values equal cor.test() as well. For Spearman there is one genuine difference: when a pair has no tied values, cor.test() switches to an exact test, while rcorr and this matrix keep the t approximation. The tool says so on screen when that applies, because a matrix that used an exact test in some cells and an approximation in others would not be comparable across cells.
What counts as a strong correlation?
It depends entirely on the field, and the popular cutoffs (0.1 small, 0.3 medium, 0.5 large) are rules of thumb Cohen himself hedged. In physics an r of 0.9 can be disappointing; in psychology 0.3 can be a solid result. A more useful habit than labelling: square it. An r of 0.5 shares 25% of the variance, which leaves 75% unexplained. And always look at a scatter plot, because very different shapes produce identical r values.
Why is the diagonal always 1?
Because a column is perfectly correlated with itself. The diagonal carries no information, which is why it is greyed out here and why rcorr puts NA in the p-value matrix along it: there is no hypothesis left to test. The n on the diagonal is still useful though, since it tells you how many non-missing values that column has.
My matrix is not positive definite. Why?
Almost always pairwise deletion. Because each cell is computed from a different subset of rows, the resulting matrix need not be internally consistent, and it can imply relationships no single dataset could produce. Anything that inverts the matrix (factor analysis, PCA, some regressions) will then fail or return nonsense. Switch to listwise deletion, or impute the gaps properly, when the matrix is an input to another model rather than something you are reading.
Does correlation imply causation?
No. Two columns can move together because one causes the other, because a third variable drives both, because of how the sample was selected, or by chance. Nothing in r, p or n distinguishes those. If the question is causal, you need a design or an explicit causal model. The confounder picker is the tool for that side of the problem.