Correlation matrix from a CSV
Drop in a CSV and every pair of numeric columns is correlated, with Pearson or Spearman, and shown as a shaded matrix plus a ranked list of the strongest pairs. Each cell reports how many rows it rests on, because a coefficient computed on four rows is not a finding. It runs in this tab, so nothing is uploaded.
Want each column described on its own first? Run the summary statistics
A grid is evidence. A ranked list is the answer.
Twelve numeric columns produce a matrix of 144 cells, of which 66 say anything new. Nobody scans that. What people actually want is the short list: which two columns move together most, how strongly, and how much data is behind the claim. So this page renders the matrix, because you should be able to check the working, and then puts the ranked pairs underneath it, because that is the part you read.
Each entry in the list carries four things: the two column names, the coefficient to three decimals, the number of rows the two columns share, and a plain reading such as "strong positive" or "no useful relationship". That last one is not decoration. A coefficient of 0.31 sounds like something until it is described as weak, at which point most people correctly stop caring about it.
The shading in the matrix uses five block characters rather than colour, so the whole report survives being pasted into a ticket, a pull request comment or a terminal. Solid for 0.9 and above, dark for 0.7, medium for 0.4, light for 0.2, and dots below that. The scale runs on the absolute value, so a strong negative relationship is as visually obvious as a strong positive one.
Worked example: where Pearson and Spearman part company
Here is growth.csv, six rows, three columns:
x,cubed,noise
1,1,9
2,8,3
3,27,7
4,64,1
5,125,6
6,216,4
The relationship between x and cubed could not be more perfect. Every time x goes up, cubed goes up. There is no randomness at all. Yet Pearson reports about 0.93, not 1, because Pearson is measuring how close the points sit to a straight line and this curve bends. Switch the method to Spearman and the answer is exactly 1.000, because the ranks of x are 1 to 6 and the ranks of cubed are also 1 to 6, and on the ranks the relationship is a perfect line.
That 0.07 gap is the whole reason both methods are on this page. Pearson at 0.93 is a strong result, so nobody would miss the relationship here. But apply the same shape to a noisier pair and Pearson can slide to 0.6 while Spearman stays near 0.9, and a person looking only at Pearson concludes there is not much there. Diminishing returns curves do this constantly: spend against reach, tenure against productivity, dose against effect.
The report for that file looks like this:
Pearson correlation for growth.csv
x cubed noise
x ██ 1.00 ██ 0.93 ··-0.14
cubed ██ 0.93 ██ 1.00 ··-0.09
noise ··-0.14 ··-0.09 ██ 1.00
Shading: ██ 0.9+ ▓▓ 0.7+ ▒▒ 0.4+ ░░ 0.2+ ·· below 0.2
Strongest pairs
x / cubed r = 0.930 n = 6 very strong positive
x / noise r = -0.140 n = 6 no useful relationship
cubed / noise r = -0.090 n = 6 no useful relationship
Six rows is far too few to conclude anything, and the page says so: any pair resting on fewer than ten shared rows triggers a warning that a correlation on that little data moves a long way on one row. The example is here to show the mechanics, not to make a claim about x and noise.
Blanks, and why every cell has its own n
Real files have gaps, and there are two ways to handle them. Listwise deletion throws away any row that is blank in any column before computing anything, so every cell of the matrix rests on the same rows. It is tidy, and it is dangerous: one sparse column that is only filled in a fifth of the rows quietly drags every other cell in the grid down to that fifth, and nothing on screen tells you it happened.
This page uses pairwise deletion instead. Each cell is computed on the rows where its own two columns both hold a number, and the other columns are irrelevant to it. That keeps a well-populated pair at full strength no matter what else is missing. The honest cost is that different cells rest on different amounts of data, so the pair list reports n for every one of them and the page warns whenever a pair drops below ten shared rows.
- A column that never changes correlates with nothing. Its variance is zero and that variance is the denominator, so the answer is undefined and the cell reads
n/a. Printing zero there would claim there is no relationship, which is a different and false statement. - Which columns count as numeric follows the same rule as the rest of the site: at least nine in ten non-blank values must parse as a number. Tick columns explicitly to override that.
- Sixty columns is the ceiling. Past that the grid stops being readable and the work grows quadratically. The first sixty are used and the warning names the total.
Reading a matrix without fooling yourself
A correlation matrix is one of the easiest places in analysis to find something that is not there. Four habits keep it honest.
- Count how many pairs you looked at. Twelve columns is 66 pairs. If none of them were related at all, you would still expect a few to come back looking moderately correlated by chance alone. The top of a long ranked list is the most likely place in the whole report for a false positive to be sitting.
- Look for the column behind the pair. Ice cream sales and drowning deaths correlate because both follow the weather. In a business file the hidden third column is usually time, size or region: two metrics that both grow with headcount will correlate beautifully and tell you nothing.
- Watch for two names for the same thing. Revenue and revenue net of tax will correlate at 0.999. So will total and subtotal, and any metric with a version of itself that has been rounded, converted or lagged by a day. These are the cells that look most impressive and mean least.
- Check n before the coefficient. Read the pair list right to left. If n is small, nothing to its left matters.
The report closes with the same reminder, printed under every run: correlation is not causation, and a correlation computed on rows where both columns happened to be filled is a statement about those rows only.
Two downloads, for two different next steps
- Matrix gives the square grid: a leading column of names, then one column per column, with the coefficient to six decimal places. This is the shape a heatmap wants, and the shape you paste into a notebook.
- Pair list gives one row per pair with
column_a,column_b,r,nand the plain-English strength. This is the shape that sorts, filters and joins, so it is the one to take if you are going to do anything else with the numbers. It also carries every pair, not just the fifteen the on-screen report names.
Copy always hands over the on-screen report, shading and all, so the thing next to the button is the thing you get.
Frequently Asked Questions
What is the difference between Pearson and Spearman here?
Pearson measures how close the two columns are to a straight line. Spearman replaces each value with its rank and then measures the same thing, so it answers a looser question: when one column goes up, does the other reliably go up too, whatever the shape of the curve? Take x running 1 to 6 against x cubed. That relationship is perfect and monotonic, but it is not a straight line, so Pearson reports about 0.93 while Spearman reports exactly 1. Run both. When they disagree by a lot, the relationship is real and curved.
Why does each pair have its own row count?
Because this page uses pairwise deletion. Each cell is computed on the rows where both of its two columns hold a number, rather than throwing away any row that is blank anywhere in the file. Listwise deletion would let one sparse column silently shrink every other cell in the matrix. The cost of doing it the right way is that different cells rest on different numbers of rows, so the pair list reports n for each one and the page warns when a pair has fewer than ten shared rows.
What does the shading mean?
It is a five-step scale on the absolute value of the coefficient, so a strong negative shades as heavily as a strong positive. A solid block is 0.9 or above, a dark block is 0.7 or above, a medium block is 0.4 or above, a light block is 0.2 or above, and dots mean below 0.2. Blocks rather than colour, so the report survives being pasted into a ticket, an email or a terminal with no styling at all.
Why is a pair reported as n/a?
Either one of the two columns never changes, or the two columns share fewer than two rows where both hold a number. A column with the same value in every row has no variance, and correlation is a ratio with that variance in the denominator, so the answer is undefined rather than zero. Printing 0 would say there is no relationship, which is a different and false claim. The warnings name the pairs this happened to.
Is there a limit on how many columns it will do?
Sixty. A matrix that size is 3,600 cells and 1,770 distinct pairs, which is already past what anyone reads, and the work grows with the square of the column count. Hand it a wider file and the first sixty numeric columns are used, with a warning naming the total so you know something was left out. Ticking the columns you care about is a better answer than scrolling a wall.
Does a high correlation mean one column causes the other?
No, and this page says so at the bottom of every report. Two columns can move together because one drives the other, because something else drives both, because they are two measurements of the same underlying thing, or because you tested enough pairs that one of them was bound to look impressive. There is also a subtler trap: because these coefficients use pairwise deletion, a strong result is a statement about the rows where both columns happened to be filled, not about your whole file.
How large a file can this page handle?
Up to about 200,000 rows or 20 MB, the whole file is parsed and correlated in the page itself. Past either of those two numbers the file is handed to DuckDB running in your tab instead, which computes every pair with SQL over the file rather than building two arrays per pair in memory. The answers are the same either way, Spearman included: DuckDB's rank function is the competition rank and Spearman needs the average rank, so the query corrects for ties explicitly, and the tests run both paths over the same file and require them to agree.
Does the file leave my computer?
No. This page has no upload endpoint. JavaScript in your tab reads the file, pairs the columns up and computes every coefficient. Nothing is stored between visits, so reloading the page gives you an empty box again.
Related
See which columns move together
Free, no account, no upload. Both methods, every pair ranked, and the row count behind each one.
Back to the matrix