# Qlik Design Blog

All about product and Qlik solutions: scripting, data modeling, visual design, extensions, best practices, etc.

Announcements
QlikWorld starts MONDAY! last chance to register is now ! REGISTER NOW  Employee

## Recipe for an ABC Analysis

An ABC analysis is a dynamic bucket classification of e.g. products, based on some property, usually the sales number. The best products are your "A" products and the worst are your "C" products.

It is used in all types of business intelligence applications and can appear in many different forms: It can concern any dimension, e.g. customer, supplier, sales person, etc. and be based on any measure. The sales number is one example, but it can just as well be e.g. number of support cases, or number of defect deliveries, etc.

One way to make an ABC analysis is to use a Pareto analysis where the classification is based on the accumulated number after the entities have been sorted according to their numbers. The products contributing to the first 80% are usually the A products.

However, the Pareto analysis, as described in the above blog post, is sometimes limiting: It is for instance not easy to use several dimensions, and it is not possible to define the ABC classes as a dimension. Hence, it is sometimes better to use an alternative classification function:

The Rank.

QlikView has a Rank() function that is well suited for this purpose. With it, you can rank any dimension according to any expression. You can use several dimensions and you can define your ABC classes as dimensions. The logic is that you calculate a relative rank, i.e. you divide the rank of the product with the total number of products:

(Rank(Sum(Sales),1)-1) / Count(distinct total Product)

If this number is lower than 0.5 the product belongs to the better 50% and thus to the “A” products. Similarly you can use 0.75 as a limit for belonging to group “B”. The result will be very similar to a Pareto analysis. One possibility is to use colors to display the classification:

1. Create a bar chart and choose your dimension and your basic measure. In the example below, I use Product and Sum(Sales) labeled as “Sales”.

2. Set the color of the bars to
If((Rank(Sum(Sales),1)-1) / Count(distinct total Product) < 0.50, RGB(140,170,200),
If((Rank(Sum(Sales),1)-1) / Count(distinct total Product) < 0.75, RGB(255,200,0), LightRed()))
In QlikView you do this under the expression “Background color” and in Qlik Sense you do it under “Appearance” – “Colors and Legend” for the object.

But you can also use this method to create a field or a calculated dimension, which means that you can make the ABC classes selectable:

Aggr( If((Rank(Sum(Sales),1)-1) / Count(distinct total Product)< 0.50, 'A',
If((Rank(Sum(Sales),1)-1) / Count(distinct total Product)< 0.75, 'B', 'C')),
Product) Finally, if you want to use ranking in a two-dimensional chart, you can use the same logic. However, you must first decide how the rank should be calculated. Normally you would want the ranking to be done within each group defined by the second dimension, i.e. per column in a pivot table: The above chart shows sales per product and customer. The colors define the classes and the rank and the count is done within each column, i.e. the products are classified within each customer. The following expression was used:

If((Rank(Sum(Sales),1)-1) / Count(distinct total <Customer> Product)< 0.50, RGB(140,170,200),

If((Rank(Sum(Sales),1)-1) / Count(distinct total <Customer> Product)< 0.75, RGB(255,200,0), LightRed()))

But you may also want to do the ranking within each group defined by the first dimension, i.e. classify the customers within each product. Then you need to swap place of Customer and Product in the formula, and you need to use HRank() instead:

If((HRank(Sum(Sales),1)-1) / Count(distinct total <Product> Customer)< 0.50, RGB(140,170,200),

If((HRank(Sum(Sales),1)-1) / Count(distinct total <Product> Customer)< 0.75, RGB(255,200,0), LightRed())) Good luck in creating your ABC analysis!

HIC

Further reading related to this topic:

Recipe for a Pareto Analysis  MVP

An excellent, concise blog as always.

8,285 Views Not applicable

What is the font you used in the first chart?

8,285 Views  Employee

The first chart is created in Qlik Sense, so the font is not exposed in the UI. It is defined in a css file somewhere... Frankly, I don't know which font it is.

HIC

8,285 Views  Creator III

Hi HIC,

Tell me if I want to apply above for a set analysis such as below, how would be the expression.

many thanks.

8,285 Views  Employee

A Set Analysis expression is in principle the same as a selection. So, if you wanted to select the "A" Products according to the above definition, you could do it by using

Sum({\$<Product={"=(Rank(Sum(Sales),1)-1) / Count(distinct total Product)<0.5"}>} Sales)

In other words: You make a search in the Set analysis expression, picking out the relevant Products.

HIC

8,284 Views  Contributor III

Dear Henric,

you (c)should use (1+(Rank(Sum(Sales),1)-1)) / Count(distinct total Product) and <= instead of < otherwise your last product gets relative rank 0.

Kind regards,

Herbert

8,284 Views  Creator II

hic is the first graphic from QlikSense? or can I plot the value in the bar like the first one and above the bar for the rest in QlikView?

5,800 Views  Employee

@ Herbert Beck: Not sure I agree... In the chart below, the 1st formula is the one from the blog post above; the 2nd one is yours; and the 3rd is what you should use if you want the relative numbers to span the entire range between 0 and 1. However - if you only have one single value of X, the 1st formula will assign it to class A, the second will assign it to class C, and the third one will fail to calculate. I think that a single value should belong to class A.

@ Juan Escobar: The first graphic is indeed from Qlik Sense. It is not possible to place the numbers this way in QlikView.

HIC

5,800 Views  Contributor III

Hi HIC,

I'm trying to practice on your examples, but I probably missed something here I want to build a calculated dimension in Sense that will allow me to sort out the products for which we're selling more than what we quoted.

Below my formula - which was a straight copy of yours - but I only get A

Aggr( If((Rank(Sum(([Qty Billed]-[Qty Opp])),1)-1) / Count(distinct total [Part Number])< 0.50, 'A',

If((Rank(Sum(([Qty Billed]-[Qty Opp])),1)-1) / Count(distinct total [Part Number])< 0.75, 'B', 'C')),

[Part Number])

What am I missing?

5,800 Views  Employee

Not sure...

I would try the following:

Aggr( If((Rank(Sum(([Qty Billed])-Sum([Qty Opp])),1)-1) / Count(distinct total [Part Number])< 0.50, 'A',

If((Rank(Sum(([Qty Billed])-Sum([Qty Opp])),1)-1) / Count(distinct total [Part Number])< 0.75, 'B', 'C')),

[Part Number])

The reason is twofold: If one of the two quantities is NULL, the minus will not work. Secondly, if the two quantities are in different tables, it will not calculate correctly.

2) Create a table with Part Number as dimension and

- Sum(([Qty Billed])-Sum([Qty Opp])

- Rank(Sum(([Qty Billed])-Sum([Qty Opp])),1)-1

- (Rank(Sum(([Qty Billed])-Sum([Qty Opp])),1)-1) / Count(distinct total [Part Number])

as Measures (Just to debug)

HIC

5,800 Views