Find outliers in a CSV
Pick a numeric column and one of four detection methods, and this page marks the values that sit outside the fences, tells you exactly where those fences fell, and lets you flag, keep or remove the rows. IQR at 1.5x or 3x, a z-score at 2 or 3 sigma computed with the sample standard deviation, or the modified z-score for a column with a long tail. Fences can be drawn per group. Everything runs in this tab and no file is uploaded.
Want the whole distribution rather than its edges? Run the percentile summary
The four methods disagree, and that is the point
There is no definition of an outlier. There are several rules of thumb, they were designed for different shapes of data, and on the same column they will hand you different answers. A tool that offers one method and calls its output "the outliers" is hiding a choice it made on your behalf. Here is what each one is actually doing.
- IQR fences at 1.5x. Sort the column, take the value a quarter of the way up (Q1) and the value three quarters of the way up (Q3), and call the distance between them the interquartile range. The fences sit one and a half of those below Q1 and above Q3. This is Tukey's rule from 1977 and it is exactly what the whiskers of a box plot mark, which means the outliers this finds are the dots your chart already draws. It assumes nothing about the shape of the column, which is why it is the default here.
- IQR fences at 3x. The same construction, twice as far out. Tukey called these the outer fences and the values beyond them "far out". Use it when the 1.5x rule flags a tenth of your file and you only want the values that are genuinely indefensible.
- Z-score at 2 or 3 sigma. How many standard deviations a value sits from the mean. Familiar, fast, and quietly unreliable, because both the mean and the standard deviation are computed from a set that includes the outliers. One extreme value drags the mean toward itself and inflates the spread, and the fence moves out to accommodate the very row you were trying to catch. Reach for this only when the column is roughly symmetric and the extremes are mild.
- Modified z-score, threshold 3.5. Replace the mean with the median and the standard deviation with the median absolute deviation, scaled by 0.6745 so the number is comparable to an ordinary z-score. Iglewicz and Hoaglin's recommendation, and the right answer for anything with a long tail: revenue per customer, session length, claim size, file size. The median moves very little when you add an extreme value, so the fence does not run away from the thing it is measuring.
One detail worth stating plainly, because it is where free tools quietly differ. The z-score here uses the sample standard deviation, dividing by n minus one. Dividing by n instead makes the spread look smaller, pulls the fences in, and produces extra outliers that are not outliers under the convention every textbook and every spreadsheet uses. On the eight-value column 2, 4, 4, 4, 5, 5, 7, 9 the two conventions put the upper 2-sigma fence at 9.0 and 9.276 respectively. Anything landing between those two numbers is a false positive from the wrong divisor.
Worked example: eleven values you can check by hand
Here is baskets.csv, small enough to verify with a pencil:
store,basket
S-01,22
S-02,24
S-03,25
S-04,26
S-05,27
S-06,28
S-07,29
S-08,31
S-09,33
S-10,35
S-11,410
Eleven values. Sorted, the median is the sixth, 28. Q1 sits at position 2.5 between 24 and 25, so 24.5; Q3 sits at position 7.5 between 31 and 33, so 32. The interquartile range is 7.5, and the 1.5x fences land at 24.5 minus 11.25 and 32 plus 11.25, which is 13.25 to 43.25. Only 410 falls outside. Leave the action on Flag and the download is:
store,basket,is_outlier,outlier_score,outlier_bounds
S-01,22,no,-0.3333,13.25 to 43.25
S-02,24,no,-0.0667,13.25 to 43.25
S-03,25,no,0,13.25 to 43.25
...
S-10,35,no,0.4,13.25 to 43.25
S-11,410,yes,50.4,13.25 to 43.25
The score is in the method's own units, so it means something different per method and the page never mixes them up. Under IQR it counts interquartile ranges past the nearer quartile: 410 is 50.4 IQRs above Q3, and a value sitting inside the quartiles scores 0. Under a z-score it is standard deviations from the mean. Under the modified z-score it is the scaled deviation from the median. The outlier_bounds column repeats the fences on every row, which looks redundant until you use the per-group option and every group has different ones.
Now switch the method to z-score beyond 3 standard deviations and watch the tool fail in the instructive way. The mean of these eleven values is 62.7 and the sample standard deviation is 115.2, because 410 dominates both. Three sigma above the mean is 408.3, so 410 scrapes past by less than two, and at 2 sigma it would not be flagged at all. The single most obvious outlier in the column almost escapes the most famous outlier test, which is the whole argument for the two robust methods sitting next to it. Switch to the modified z-score and it is caught with room to spare: the median is 28 and the median absolute deviation is 4, so the fence sits at 28 plus 3.5 times 4 divided by 0.6745, or 48.8.
The summary strip above the table prints the fences in full every time, in the form fences 13.25 to 43.25 (Q1 24.5 and Q3 32, IQR 7.5, fences at 1.5x). That sentence is the one thing a reader needs in order to disagree with the tool, and no number in it is ever abbreviated. A fence description that renders two different years as "2k to 2k" is worse than printing nothing at all, because it tells you the bounds are identical when they are four years apart.
Fences per group, for when normal depends on context
A single fence across a whole column assumes every row is comparable to every other. Often it is not. A basket size of 90 is ordinary in a flagship store and startling in an airport kiosk. A response time of 800 milliseconds is fine for a report endpoint and alarming for a health check. Pool those together and you get the worst of both: the genuinely odd rows in the small group hide inside the spread of the big one, and ordinary rows from the big group get flagged for being large.
Set Fences per group to the column that names the context and each group is measured against itself. Every group gets its own quartiles, its own spread and its own bounds, and the outlier_bounds column starts earning its place: each row carries the fences that judged it.
- Groups too small to judge are reported, not passed. Fewer than three values, or no spread at all, and there is no honest fence to draw. Those rows come back marked
noand the warnings name the groups so you know they were not really examined. - A nearly unique grouping column is refused. Group by an order id and every group has one row, every group has no spread, and the tool finds nothing while appearing to work. Rather than hand back that empty answer it stops and says the column is nearly unique, naming the distinct count against the row count.
- Blank group values form their own group. They are not dropped, because a blank category is usually itself a finding.
Flag, keep or remove
The action decides what comes back, and the default is deliberately the least destructive one.
- Flag, keep every row. The whole file comes back with three columns added:
is_outlier,outlier_scoreandoutlier_bounds. Nothing is lost, and you can sort or filter on the flag in a spreadsheet afterwards. This is the default because an outlier is a candidate for investigation and not a verdict. - Keep only the outliers. Just the flagged rows, with the score and the bounds. This is the shortlist to read through, and it is usually short enough to read.
- Remove the outliers. The surviving rows, with no extra columns, in their original order. Useful when you already know the extremes are junk from a broken sensor or a test account. The summary always names how many rows went, so a silent quiet deletion is not possible.
If your file already has a column called is_outlier from a previous pass, it is not overwritten. The new column becomes is_outlier_2, and the same rule applies to the score and bounds columns.
Gotchas worth knowing
- An outlier is not an error. It is a value far from the others, which is arithmetic, not judgment. The best customer in the file and a misplaced decimal point look identical to every method on this page. Read the rows before you decide which you have.
- Blanks and non-numbers are left out and counted. A cell holding
N/Aor nothing at all cannot be measured against a fence, so it is excluded from the calculation and reported in the warnings. It stays in the file under Flag, markedno. - A column with no spread has no outliers. If every value is the same, or the middle half of the values are identical so the IQR is zero, no fence can be drawn. The tool says so rather than dividing by zero and flagging everything.
- Percentages and rates deserve care. A conversion rate bounded between 0 and 1 has fences that will happily run past those bounds, which is mathematically correct and practically useless. The IQR method is the least bad of the four here, but consider whether the outlier question is the right one for a bounded column.
- Running the tool twice is not the same as running it once. Remove the outliers, feed the result back in, and a fresh set appears, because the fences were recomputed on the narrower column. That is not a bug and it is not convergence toward truth. Decide on one pass.
- Nothing leaves the tab. The file is read, sorted and measured by JavaScript in your browser. There is no upload endpoint on this page.
Frequently Asked Questions
Which outlier method should I use?
IQR at 1.5x if you have no reason to prefer another. It makes no assumption about the shape of the column and it is what a box plot draws, so the answer matches the chart. Use the modified z-score when the column has a long tail, such as revenue per customer, because the median and the median absolute deviation are not dragged around by the very values you are hunting. Use a z-score only when the column is roughly symmetric. Use IQR at 3x when you want the genuinely absurd values and nothing else.
Why does a z-score miss the obvious outlier in my column?
Because the outlier is inflating the standard deviation it is being measured against. One value of 1,000 in a column that otherwise runs 1 to 9 pushes the standard deviation up so far that 1,000 sits inside three sigma. This is the standard failure of z-scores and it is the reason the modified z-score exists: the median absolute deviation barely moves when you add an extreme value, so the fence stays where it should be and the 1,000 is caught.
Do you divide by n or by n minus one?
By n minus one, the sample standard deviation. Your CSV is a sample of something, and that is the convention every statistics textbook and every spreadsheet uses. It matters: on a column of 2, 4, 4, 4, 5, 5, 7, 9 the population standard deviation is exactly 2 and the sample one is 2.138, so a 2-sigma fence sits at 9.0 under one convention and 9.276 under the other. Anything between those two numbers is called an outlier by a tool that divides by n and is not one under the convention you were taught.
What does the per-group option do?
It draws a separate fence inside each group instead of one fence across the whole column. A basket size of 90 is unremarkable in a flagship store and absurd in a kiosk, and a single fence across both cannot see that. Pick the column that names the group and every group gets its own quartiles, its own spread and its own bounds. Groups too small or too flat to judge are reported rather than silently passed.
What is in the download?
That depends on the action. Flag keeps every row and appends three columns: is_outlier as yes or no, outlier_score in the method's own units, and outlier_bounds naming the two fences the row was judged against. Keep only the outliers returns just those rows with the score and bounds. Remove returns the surviving rows and nothing extra. A column called is_outlier already in your file is not overwritten; the new one becomes is_outlier_2.
Should I delete the rows it finds?
Usually not, and certainly not before you have looked at them. An outlier is a value far from the others, which is a statement about arithmetic rather than about correctness. Some are typos, some are the most interesting rows in the file, and deleting the second kind is how an analysis ends up saying nothing. Flag first, read the rows, and only then decide. That is why Flag is the default action here and not Remove.
Does the file leave my computer?
No. This page has no upload endpoint. JavaScript in your tab reads the file, sorts the column, computes the fences and writes the result. Nothing is stored between visits, so reloading the page gives you an empty box again.
Related
See which rows are the odd ones out
Free, no account, no upload. Pick a column, pick a method, read the fences, decide for yourself.
Back to the outlier finder