ABC / Pareto Analysis: Practical Guide for Data-Driven Decisions
By MCP Analytics Team | Published , updated
ABC analysis ranks items by how much they contribute, then splits them into three groups: A (the few that matter most), B (the middle) and C (the many that matter least). Pareto analysis is the same idea, usually drawn as a chart and tied to the "80/20" idea that a small share of causes produces most of the effect. The items can be products, customers, defect causes or tasks.
The method is simple. The choices around it are where it goes wrong: what you rank by, where you draw the lines, and how often you redo it. This guide runs all three on a small data set so you can see the effect, with the code and the output.
Two terms first. An SKU is one product you stock. Contribution is revenue minus the costs that rise and fall with each sale (cost of goods, shipping, payment fees). Cumulative share is the running total of value as you walk down the ranked list, as a percent of the grand total.
To run a Pareto analysis on your own file, see the Pareto analysis page or try the free Pareto analysis tool.
Where the 80/20 Idea Comes From
Pareto is named for the economist Vilfredo Pareto, who observed that about 80% of the land in Italy was owned by about 20% of the people. Joseph Juran later applied the idea to quality control and management, and preferred to call it "the vital few and the useful many" (Pareto principle, Wikipedia). That same source describes 80/20 as shorthand and a rule of thumb, and says real cases can sit nearer 90/10 or 70/30.
ABC analysis applies the ranking to inventory. The same reference says it has no fixed thresholds for each class, and that the proportions are set from your objectives (ABC analysis, Wikipedia). So "A is 80% of value" is a convention you may adopt, not a result you can expect from every data set.
A Worked Example You Can Re-Run
The data below is synthetic: 300 made-up SKUs generated with a fixed random seed. Revenue is drawn from a skewed (lognormal) distribution and each SKU gets its own margin between about 2% and 45%. It is not data from a real business. It is built so you can see what changes when you rank by revenue versus by contribution. The script needs only numpy. Run it with python3 abc.py.
import numpy as np
rng = np.random.default_rng(11)
n = 300
revenue = rng.lognormal(mean=8.0, sigma=1.1, size=n).round(0)
margin = (0.02 + 0.43 * rng.beta(1.5, 3.0, size=n)).round(3)
contrib = (revenue * margin).round(0)
def classify(value, a=0.80, b=0.95):
order = np.argsort(-value)
share = np.cumsum(value[order]) / value.sum()
cls = np.empty(len(value), dtype="<U1")
# an item is A if the share BEFORE adding it is below the cutoff
before = share - value[order] / value.sum()
cls[order] = np.where(before < a, "A", np.where(before < b, "B", "C"))
return cls
def summary(label, value, cls):
out = [label]
for k in "ABC":
m = cls == k
out.append(f"{k}: {m.sum():3d} items ({m.mean():5.1%}) hold {value[m].sum()/value.sum():5.1%}")
print(" ".join(out))
rev_cls = classify(revenue)
con_cls = classify(contrib)
print(f"items {n}, total revenue {revenue.sum():,.0f}, total contribution {contrib.sum():,.0f}")
summary("by revenue ", revenue, rev_cls)
summary("by contribution", contrib, con_cls)
print("\ntransition table (rows revenue class, cols contribution class)")
for r in "ABC":
print(r, [int(((rev_cls == r) & (con_cls == c)).sum()) for c in "ABC"])
changed = (rev_cls != con_cls).sum()
print("items whose class changes:", changed, f"({changed/n:.1%})")
revA = rev_cls == "A"
print("revenue-A items:", revA.sum(), " of which not A by contribution:", (revA & (con_cls != "A")).sum())
print("contribution-A items not A by revenue:", ((con_cls == "A") & ~revA).sum())
print("avg margin of revenue-A items %.1f%%, of contribution-A items %.1f%%" % (
100*np.average(margin[revA], weights=revenue[revA]), 100*np.average(margin[con_cls=="A"], weights=revenue[con_cls=="A"])))
print("\ncutoff sensitivity (A group size by contribution)")
for a in (0.70, 0.80, 0.90):
c = classify(contrib, a=a, b=min(a + 0.15, 0.99))
print(f"A cutoff {a:.0%}: {(c=='A').sum()} items ({(c=='A').mean():.1%})")
print("\ncapacity cutoff: top 30 by contribution hold %.1f%%, top 60 hold %.1f%%" % (
100*np.sort(contrib)[::-1][:30].sum()/contrib.sum(), 100*np.sort(contrib)[::-1][:60].sum()/contrib.sum()))
# next period: same margins, revenue moves by random noise
rev2 = (revenue * rng.lognormal(0, 0.3, size=n)).round(0)
con2 = (rev2 * margin).round(0)
cls2 = classify(con2)
print("\nnext period (revenue noise sigma 0.3, margins unchanged)")
print("items that change class:", (cls2 != con_cls).sum(), f"({(cls2 != con_cls).mean():.1%})")
print("A items that drop out of A:", ((con_cls == "A") & (cls2 != "A")).sum(), "of", (con_cls == "A").sum())
# show a few revenue-A that fall
fall = np.where(revA & (con_cls != "A"))[0]
fall = fall[np.argsort(-revenue[fall])][:4]
print("top revenue-A that drop")
for i in fall: print(i+1, int(revenue[i]), margin[i], int(contrib[i]), rev_cls[i], con_cls[i])
rise = np.where(~revA & (con_cls == "A"))[0]
rise = rise[np.argsort(-contrib[rise])][:4]
print("rise")
for i in rise: print(i+1, int(revenue[i]), margin[i], int(contrib[i]), rev_cls[i], con_cls[i])
An item is put in A if the cumulative share before adding it is still below 80%. It goes in B if that share is still below 95%. Everything else is C. These 80/95 lines are the common convention, used here as a starting point.
Result 1: the 80/20 split did not appear
| Ranked by | A items | B items | C items |
|---|---|---|---|
| Revenue | 134 items (44.7%) hold 80.2% | 88 items (29.3%) hold 14.9% | 78 items (26.0%) hold 4.9% |
| Contribution | 113 items (37.7%) hold 80.2% | 91 items (30.3%) hold 14.8% | 96 items (32.0%) hold 5.0% |
Total revenue is 1,490,689 and total contribution is 253,407. To reach 80% of the value, you need 38% to 45% of the items, not 20%. The data here is less skewed than the "vital few" picture suggests. That is a feature of this made-up data set, and your own data may be steeper or flatter. The lesson is to check, not to assume.
Result 2: ranking by revenue and by contribution disagree
| Class by revenue (rows) | A by contribution | B by contribution | C by contribution |
|---|---|---|---|
| A (134 items) | 94 | 36 | 4 |
| B (88 items) | 19 | 42 | 27 |
| C (78 items) | 0 | 13 | 65 |
99 of the 300 items (33.0%) land in a different class depending on which measure you use. Of the 134 revenue-A items, 40 are not A by contribution. In the other direction, 19 items are A by contribution but not by revenue. Here are the four biggest revenue-A items that drop to B, and the four biggest contribution-A items that were B by revenue:
| SKU | Revenue | Margin | Contribution | Revenue class | Contribution class |
|---|---|---|---|---|---|
| 137 | 12,766 | 3.8% | 485 | A | B |
| 85 | 12,482 | 3.9% | 487 | A | B |
| 3 | 11,467 | 3.2% | 367 | A | B |
| 71 | 9,846 | 3.3% | 325 | A | B |
| 223 | 3,289 | 35.8% | 1,177 | B | A |
| 89 | 3,899 | 29.6% | 1,154 | B | A |
| 266 | 2,928 | 37.0% | 1,083 | B | A |
| 99 | 2,927 | 36.5% | 1,068 | B | A |
The pattern is the one to watch for: large sales at thin margins look important by revenue, and small sales at fat margins get missed. Which measure is right depends on your decision. If the question is "where should our money and attention go", contribution is closer to the point. If the question is "how much shelf space do we need", revenue or units may fit better.
Result 3: the cutoff changes the size of group A a lot
| A cutoff (cumulative share of contribution) | Items in A | Share of all items |
|---|---|---|
| 70% | 82 | 27.3% |
| 80% | 113 | 37.7% |
| 90% | 163 | 54.3% |
Moving the line by ten points moves group A by 31 to 50 items. If a buyer can only watch 30 items closely, none of these cutoffs fits. The other way to set the line is by capacity: pick the number of items your team can actively manage, then check what they hold. In this data the top 30 items by contribution hold 41.4% of contribution, and the top 60 hold 60.2%. That is a different answer than "80%", and it is an honest one: with this spread of values, 30 items cannot cover most of the value.
Result 4: classes move from one period to the next
To test stability, the script makes a "next period" by multiplying each SKU's revenue by random noise (lognormal, spread 0.3) and keeping each margin the same. With that moderate change, 37 of 300 items (12.3%) land in a different contribution class, and 15 of the 113 A items drop out of A. Real demand shifts are not random noise, so treat this as an illustration that classes are not fixed, not as a forecast for your business. A reasonable habit is to recalculate on a schedule and look at the items sitting just either side of a line.
What the Example Suggests, and What It Does Not
- Pick the measure to match the decision. The two rankings disagreed on one item in three here.
- Check the shape of your data before quoting 80/20. It took 38% to 45% of items to reach 80% of value.
- Set cutoffs on purpose. Either by cumulative share or by what your team can handle, and test a nearby cutoff.
- Expect movement. Classes are a snapshot of one period.
What it does not show: whether treating A, B and C items differently improves results. That needs a before-and-after or a comparison group on your own operation, and this page does not claim an effect size.
Choosing Cutoffs
Common conventions are 80/15/5 and 70/20/10 (share of value for A, B and C). They are starting points. Some ways to decide:
- By cumulative share. Easy to explain and repeat. Group sizes are whatever the data gives, as the table above shows.
- By capacity. Decide how many items your team can give custom reorder points or a named owner, then call those A. The share of value they hold is an output you read, not a target.
- By the gaps. Look at the ranked values for a natural break, where value falls off sharply, and draw the line there.
Prepare the Data First
Dirty inputs can change the ranking, so check these before you run it:
- Returns and cancellations. Net them out. A $5,000 order with $3,000 returned is $2,000 of value.
- One-off bulk orders. A single order of 500 units can lift an item that normally sells 5 at a time. Consider ranking with and without it.
- Promotions. Margin during a discount is not your usual margin. Note it, or use a window that includes both.
- Period length. A short window is noisy and a seasonal item will swing. Use a window long enough to cover your cycle, or compare the same season year over year.
- New items. With little history, a new item will look like a C. Mark new items so they are reviewed rather than ignored.
What to Do With the Classes
The labels only matter if they change what people do. Write the treatment down before you run the analysis. Here is one way to set it up. The review rhythm is a suggestion, so change it to fit your business.
| Class | Possible treatment |
|---|---|
| A | Named owner, custom reorder point, frequent review, a backup supplier where one exists |
| B | Standard reorder formula, periodic review |
| C | Simple min/max rules, fewer touches, a periodic check on whether to keep the item |
One limit to know: ABC ranking looks at each item alone. An item that is C on its own may be bought together with an A item, so a basket check (which items sell together) is a useful second look before you cut anything.
Beyond Inventory
The same ranking works on customers (rank by contribution after cost to serve, and add a trend view so a shrinking customer is not hidden), on marketing categories, on support tickets by cause, and on how you spend your own time. Where one number is not enough, researchers have extended ABC analysis to rank on several criteria at once, such as cost and how critical an item is (Flores and Whybark, 1986, listed in the sources below).
Run It on Your Own Data
With MCP Analytics you upload a CSV with one row per item and a value column. A tested statistical method ranks the items and computes the cumulative shares, and you get a written report. It is repeatable: the same file gives the same numbers. You decide the cutoffs and what the A group should get. Start from the Pareto analysis page.
Your turn
Bring your own data and the question you actually need answered.
MCP AnalyticsData science by email Send us your data and your question, and we will reply. ds@mcpanalytics.ai
Frequently Asked Questions
They are close relatives and are often used as one method. Both rank items by how much they contribute, then group them by cumulative share. ABC analysis comes from inventory control and sorts items into A, B and C. Pareto analysis is named after Vilfredo Pareto and is used more widely, for example on defect causes or customers. The 80/20 split is a rule of thumb, not a law, and real data can land far from it.
There is no fixed rule. Splits such as 80/15/5 or 70/20/10 are conventions. Two sound ways to choose: set the cutoff by cumulative share (for example, A is the items that make up the first 80% of value), or set it by how many items your team can actively manage and see what share of value that group holds. Whichever you pick, write down the reason and test a neighbouring cutoff to see how much the group sizes change.
Use the measure that matches the decision. For where to spend inventory money or attention, contribution (revenue minus the costs that vary with each sale) is usually closer to what you care about than revenue. In the worked example on this page, 40 of the 134 items in the revenue A group dropped out of A when ranked by contribution. Ranking by units is reasonable when the question is shelf or warehouse space.
It depends on how fast your sales change. In the worked example, adding moderate random change to revenue moved 37 of 300 items (12.3%) into a different class the next period. That is a sign to recalculate on a schedule and to watch items near a cutoff, but the right schedule for your business (monthly, quarterly) is a judgment call.
Yes. Rank customers by contribution or profit instead of items. Add a time view as well, since a customer who is shrinking can still sit in group A on last year's numbers. A one-number ranking says nothing about direction.
Sources
- Pareto principle, Wikipedia. Used for the origin of 80/20 and its description as a rule of thumb.
- ABC analysis, Wikipedia. Used for the point that class thresholds are not fixed.
- Flores B.E. and Whybark D.C. (1986). Multiple Criteria ABC Analysis. International Journal of Operations & Production Management, 6(3), 38-46. Used for the multi-criteria extension.
- All numbers in the worked example come from the script on this page (synthetic data, seed 11).