Rank order data - excel

I have the loan dataset below -
Sector
Total Units
Bad units
Bad Rate
Retail Trade
16
5
31%
Construction
500
1100
20%
Healthcare
165
55
33%
Mining
3
2
67%
Utilities
56
19
34%
Other
300
44
15%
How can I create a ranking function to sort this data based on the bad_rate while also accounting for the number of units ?
e.g This is the result when I sort in descending order based on bad_rate
Sector
Total Units
Bad units
Bad Rate
Mining
3
2
67%
Utilities
56
19
34%
Healthcare
165
55
33%
Retail Trade
16
5
31%
Construction
500
1100
20%
Other
300
44
15%
Here, Mining shows up first but I don't really care about this sector as it only has a total of 3 units. I would like construction, other and healthcare to show up on the top as they have more # of total as well as bad units

STEP 1) is easy...
Use SORT("Range","ByColNumber","Order")
Just put it in the top left cell of where you want your sorted data.
=SORT(B3:E8,4,-1):
STEP 2)
Here's the tricky part... you need to decide how to weight the outage.
Here, I found multiplying the Rate% by the Total Unit Rank:
I think this approach gives pretty good results... you just need to play with the formula!
Please let me know what formula you eventually use!

You would need to define sorting criteria, since you don't have a priority based on column, but a combination instead. I would suggest defining a function that weights both columns: Total Units and Bad Rate. Using a weight function would be a good idea, but first, we would need to normalize both columns. For example put the data in a range 0-100, so we can weight each column having similar values. Once you have the data normalized then you can use criteria like this:
w_1 * x + w_2 * y
This is the main idea. Now to put this logic in Excel. We create an additional temporary variable with the previous calculation and name it crit. We Define a user LAMBDA function SORT_BY for calculating crit as follows:
LAMBDA(a,b, wu*a + wbr*b)
and we use MAP to calculate it with the normalized data. For convenience we define another user LAMBDA function to normalize the data: NORM as follows:
LAMBDA(x, 100*(x-MIN(x))/(MAX(x) - MIN(x)))
Note: The above formula ensures a 0-100 range, but because we are going to use weights maybe it is better to use a 1-100 range, so the weight takes effect for the minimum value too. In such case it can be defined as follow:
LAMBDA(x, ( 100*(x-MIN(x)) + (MAX(x)-x) )/(MAX(x)-MIN(x)))
Here is the formula normalizing for 0-100 range:
=LET(wu, 0.6, wbr, 0.8, u, B2:B7, br, D2:D7, SORT_BY, LAMBDA(a,b, wu*a + wbr*b),
NORM, LAMBDA(x, 100*(x-MIN(x))/(MAX(x) - MIN(x))),
crit, MAP(NORM(u), NORM(br), LAMBDA(a,b, SORT_BY(a,b))),
DROP(SORT(HSTACK(A2:D7, crit),5,-1),,-1))
You can customize how to weight each column (via wu for Total Units and wbr for Bad Rates columns). Finally, we present the result removing the sorting criteria (crit) via the DROP function. If you want to show it, then remove this step.
If you put the formula in F2 this would be the output:

Related

If Statements with Ranges

I need to calculate some weighted percentages with the following criteria:
If X=70% then I multiply 80% of 30%
If X=75% then I multiply 100% of 30%
If X=80% then I add 10% to the 30%
Anything beyond 80% is at most 40%.
How do I calculate what this percentage will be if say for example, X = 73%? It's expected to be over 80%.
1. If X<70%
2. If 70%<=X<75%
3. If 75%<=X<80%
if X = 69% it will be less than 24% (less than 80% of 30%)
if X = 73%, the percentage will be between 24%-30% (between 80% and 100% of 30%), how can I determine how this is scaled?
if X = 81%, then it will be at most 40%
I recommend to avoid the IF statement and replace it with INDEX/MATCH because of its greater flexibility. Basically, you have two multipliers. One varies between 30% and 40%, the other between 80% and 100% of the result of the first. Use the MATCH function to determine the bracket, for example, =MATCH($A$1*100,{0,65,70,72.5,75,77.5,80,82.5,85},1). Here your example of 73% is found in A1. The numbers between curly braces allow for 9 categories: less than 65%, 65% to less than 70%, 70% to less than 72.5% ... and 85% and over. There can be as many brackets as you like, using any numbers that suit your needs. Just make sure that they are in ascending order.
Next, create the index, for example, =INDEX({30,30,31,32,33,35,38,40,42},5). The key point here is that there should be as many elements in the index as there are brackets in the MATCH function. My above sample INDEX will return 33 because the 5th index element is specified. In the formula below the 5 is replaced by the MATCH function.
=INDEX({30,30,31,32,33,35,38,40,42},MATCH($A$1*100,{0,65,70,72.5,75,77.5,80,82.5,85},1))
This function will return 32(%) if A1=72%. Adjust the Index and/or Match arrays to return the result you need. Divide the result by 100 to convert the result to percent.
Given the flexibility of the suggested method I think you may not need to resort to twin multiplications. However, if your system requires it, just build the second multiplier in the same way as the first. =INDEX({75,80,85,90,95,100},MATCH($A$1*100,{0,65,70,75,80,85},1)) Then multiply both with each other.
=INDEX({75,80,85,90,95,100},MATCH($A$1*100,{0,65,70,75,80,85},1))*INDEX({30,30,31,32,33,35,38,40,42},MATCH($A$1*100,{0,65,70,72.5,75,77.5,80,82.5,85},1))/10^2
Observe the division by 100 at the end which converts the result (here, based on A1=73%) of 32 * 85 = 2720 into 27.2. Change the divisor to 10^4 in order to obtain 27.2%

(Excel)Calculating costs, where prices differ based on quantities

I'm looking for some help as I'm not really sure of the correct terms to use on my query below, so whilst normally I would google this, I'm not really sure what to search for.
I need to work out the total cost for something, where you have a flat rate, and then an additional cost that changes depending on how much of something you have.
So an example, you get expenses paid for millage. If you drive 0-20 miles, you'll get £10. Between 30-50 miles you get 50p per mile. Between 51-100 miles you get £1 per mile and so on, added onto the base rate of the initial £10 you'd get paid as standard.
It's not the best example, but hoping it gives an idea of what I'm after.
If I was doing this by hand I'd know how to work it out, but I'm not to sure what kind of formula I need to be using - I've never had to work with complex formulas past "=sum" until now.
If anyone has any examples they can share or can point me in the right direction of what kind of things to google I'd be most grateful !
Thanks
Well, here is one way, but you don't state what the rate is between 21 and 30...
very basic, but you should be able to edit and expand as you want.
Do note that the limits (30 miles, 50 miles) and rates used in the formula all come from the sheet - so if the 30 mile limit changes to 25 miles - all you need to do is change cell A7...
I apologize for not answering sooner, but I find this question a bit difficult to address due to the complexity of formulas we can encounter. I know the one you documented is not the most complex one we might encounter, but I was not sure if that was your actual problem or if it was intended as a simple example. I have seen a variety of other things which have often thrown me for a loop.
For example, take this set of rules:
Minimum Fee is $23.50 up to $500
$501 - $2,000 = $3.05 per 100 unit increment
$2,001 - $25,000 = $14.00 per 1000 unit increment over $2,000
$25,001 - $50,000 = $10.10 per 1000 unit increment over $25,000
$50,001 - $100,000 = $7.00 per 1000 unit increment over $50,000
$100,001 - $500,000 = $5.60 per 1000 unit increment over $100,000
$500,001 - $1,000,000 = $4.75 per 1000 unit increment over $500,000
$1,000,001 - $9,999,000 = $3.65 per 1000 unit increment over $1,000,000
$10,000,001 and up = $3.65 per 1000 unit increment over $10,000,000
It does not look too different from yours except that there is an increment of something other than a single unit. In other words for the $501 to $2,000 range, $501 to $600 would all get the same additional $3.05 incremental charge. Another dollar would actually double this because it jumps to the next increment. Like your example, each range builds on the prior range. Assuming that these amounts are in colums A through F:
i Low High Fee Base Fee Per
0 1 500 23.50
1 501 2,000 $3.05 100
2 2,001 25,000 $23.50 1000
3 25,001 50,000 $10.10 1000
4 50,001 100,000 $7.00 1000
5 100,001 500,000 $5.60 1000
6 500,001 1,000,000 $4.75 1000
7 1,000,001 9,999,999 $3.65 1000
8 10,000,000 $3.65 1000
Note also that the rate declines as the amounts increase whereas yours appears to increase.
What I did with this is create a maximum value in Column H as follows:
i Max
0 =E3
1 =INT((C4-C3)/F4)*D4
2 =INT((C5-C4)/F5)*D5
3 =INT((C6-C5)/F6)*D6
4 =INT((C7-C6)/F7)*D7
5 =INT((C8-C7)/F8)*D8
6 =INT((C9-C8)/F9)*D9
7 =INT((C10-C9)/F10)*D10
8
The first one, where i is zero, is simply the base fee. The others are computed and copied. There is no maximum for the last row. I did not really think I needed this column but it made it easier to devise the formulas.
Assuming that I put an amount to evaluate in Cell I2, it will be evaluated as follows where the formula in row 3 (where i=0) is the set fee but all others are basically a copied formula:
i 4,950
0 =IF(I$2>=$B3,$H3,0)
1 =IF(I$2>=$B4,IF($H4="",INT((I$2-$C3)/$F4)*$D4,MIN($H4,INT((I$2-$C3)/$F4)*$D4)),0)
2 =IF(I$2>=$B5,IF($H5="",INT((I$2-$C4)/$F5)*$D5,MIN($H5,INT((I$2-$C4)/$F5)*$D5)),0)
3 =IF(I$2>=$B6,IF($H6="",INT((I$2-$C5)/$F6)*$D6,MIN($H6,INT((I$2-$C5)/$F6)*$D6)),0)
4 =IF(I$2>=$B7,IF($H7="",INT((I$2-$C6)/$F7)*$D7,MIN($H7,INT((I$2-$C6)/$F7)*$D7)),0)
5 =IF(I$2>=$B8,IF($H8="",INT((I$2-$C7)/$F8)*$D8,MIN($H8,INT((I$2-$C7)/$F8)*$D8)),0)
6 =IF(I$2>=$B9,IF($H9="",INT((I$2-$C8)/$F9)*$D9,MIN($H9,INT((I$2-$C8)/$F9)*$D9)),0)
7 =IF(I$2>=$B10,IF($H10="",INT((I$2-$C9)/$F10)*$D10,MIN($H10,INT((I$2-$C9)/$F10)*$D10)),0)
8 =IF(I$2>=$B11,IF($H11="",INT((I$2-$C10)/$F11)*$D11,MIN($H11,INT((I$2-$C10)/$F11)*$D11)),0)
The Fee for this is the sum of all of the rows (labeled i, 0 through 8 above). in this example, it would be 23.50 plus 45.75 plus 28.00 for a total of 97.25.
Not too bad. How about a set like this:
No fee if $1,000 or less
$1,001 - $5,000 = $80.00 + 3% of excess over $1,000.00 per 100 unit increment
$5,001 - $10,000 = $250.00 + 2% of excess over $5,000.00 per 500 unit increment
$10,001 - $25,000 = $350.00 + 1% of excess over $10,000.00 per 1000 unit increment
$25,001 and Over = $520.00 + 3/4% of excess over $25,000.00 per 1000 unit increment
In your formula, the initial flat amount never changes and once you've computed the amount for that range, other ranges build upon it. Here, there are steps. For example at $1,000 the fee is zero, but at $1,001, it jumps to $80 as if there were an $80 fee for the first 1000. Without boring you with the entire table, Here is the formula for computing the range from 5,001 to 10,000 assuming that G2 contains the amount to use and Row 5 colums A through E are the following:
Low High Rate Minimum Increment
5,001 10,000 2.00% 250 500
=($D5+$C5*INT(($G$2-($A5-1))/$E5)*$E5)*($G$2>=$A5)*OR($B5="",$G$2<=$B5)
The formula simply looks at the current row and does the computation if the amount in G2 falls within the range from Column A to Column B.
A simplification of all of the above comes when each range cumulatively builds on the prior ranges AND the rate of payment is always increasing, like the U.S. Tax Tables:
Over Not Over
0 9,525 10% of taxable income
9,525 38,700 $952.50 plus 12% of the excess over $9,525
38,700 82,500 $4,453.50 plus 22% of the excess over $38,700
82,500 157,500 $14,089.50 plus 24% of the excess over $82,500
157,500 200,000 $32,089.50 plus 32% of the excess over $157,500
200,000 500,000 $45,689.50 plus 35% of the excess over $200,000
500,000 $150,689.50 plus 37% of the excess over $500,000
Here, we can use something referred to as the "deskpad method" to shortcut the computation
Assuming that the amount to be evaluated is in G1 and these are in column A through C starting in Row 1:
Over Not Over Rate
0 9,525 10.0%
9,525 38,700 12.0%
38,700 82,500 22.0%
82,500 157,500 24.0%
157,500 200,000 32.0%
200,000 500,000 35.0%
500,000 37.0%
We compute the amount based on G1 as follows:
=ROUND(SUMPRODUCT($C$2:$C$8-$C$1:$C$7,$G$1-$A$2:$A$8,N($G$1>$A$2:$A$8)),0)
Note: this is not entered as an array formula.
How does this relate to your question. If the need is as simple as you stated (in other words, the rate is always increasing and we do not have any "steps" in the reimbursement, we can compute it similarly to the U.S. Tax computation.
I created these values in columns A through D starting in row 1:
Over Not Over
0 20 £- Flat Amount of £10.00
20 50 £0.50 £10.00 plus £.50 per mile over 20 miles
50 100 £1.00 £25.00 plus £1.00 per mile over 50 miles
100 £1.50 £75.00 plus £1.50 per mile over 100 miles
where column D is just descriptive. I put the £10.00 flat fee in Cell E1.
Assuming that G1 contains the number of miles, we would compute the reimbursement as:
=$E$1+ROUND(SUMPRODUCT($C$2:$C$5-$C$1:$C$4,$G$1-$A$2:$A$5,N($G$1>$A$2:$A$5)),2))
For example, when G1 is 52 miles, the computation is £27.00
Note: this is not entered as an array formula.
So, if this is the situation, what you would need is a place to house Columns A through C, a place to house the flat amount and a formula similar to what I provided to compute the reimbursement based on the cell housing the number of miles.
Please note that all the earlier items indicate that this formula will not be so simple if the rate is stepped or the rate declines or if the incremental unit is something other than 1 mile.
I hope that some of this makes sense. Good luck.
Things to google : "nested IF in excel"
How to do this in a one-line-formula : enter " =IF(A1<20,10,IF(A1>50,IF(A1>50,10+A1,"u"),0.5*(A1))) " in B1, your milage in A1.
To learn building this :
identify the conditions :
condition1 > 0-20 miles, you'll get £10.
condition2 > between 30-50 miles you get 50p per mile
condition3 > between 51-100 miles you get £1 per mile added onto £10
put the conditions into IF() statement
For contition1 > just type " =if(a1<20,10,0) " at B2 (and try it!) (:
Note : The syntax for IF() function is if("condition","if-true-do-this","if-false-do-this")
Thus, for condition2 > " =if(a1>20,a1*0.5,0) "
And for condition3 > " =if(a1>50,if(a1>50,10+a1),0) " correction : should be " =if(a1>50,10+a1,0) "
Combining all the conditions > "=IF(A1>20,IF(A1>50,IF(A1>50,10+A1,"error"),0.5*(A1)),10) "
Notice that I changed 0 in the "if-false-do-this" part of the equation just to make sure it show something when the milage entered is less than 0.
Hope that helps. /(^_^)

Using the Excel's Rank() function to calculate allocations based on ranking and constraints

I have the following table set up
Limit Allocation Yield Ranking
$600 [to calc] 0.07% 7
$600 0.09% 6
$600 0.20% 1
$400 0.20% 1
$400 0.13% 4
$200 0.19% 3
$200 0.12% 5
Additionally, I have a constraint which I could only allocate a total of $2000 across the 7 rows here, by the rankings of their yield (so a higher yield would get everything allocated up to the limit column if there is any left overs from the $2000 total).
I was wondering how I could set up the equations so that it could perform the allocation automatically. Thanks!
I'm going to assume this table starts in A1...
In E1, put the amount you have to allocate
In B2 (and then copied to B3...B8) use the following formula
=MIN(A2,$E$1-SUMIF($D$2:$D$8,">"&D2,$B$2:$B$8))
This will work out how much has been taken by higher ranked, and take the rest, upto whatever is the lesser amount of their limit, and what is left in the pot.
There is one fault with this equation that you will need to figure out how to handle:
If there are equal ranks at the end of the distribution, then both will get the final amount. (e.g. try this with $2,001, and you will see that the 2 rows that have then rank 1 will both claim the final dollar)
Answer to solve the ties for rank causing problem. In the rank column D, add to the rank =rank(c2,$c$2:$c$8,0) + (.0000001 * row(a2)), or whatever row you are in. Then format the rank column to only show integers. Doing this makes the very small decimal addition to the rank the tie breaker so the first row with the rank's matching integer will take the allocation. Since you are adding it to the rank, it doesn't effect any totals. By changing the column format display to integer, the viewer will not be aware of the tiebreaker.

random number based on probability in Excel

How can I create a random number generator which calculates a random number based on a probability?
For example, I have the following numbers with the probability they will occur starting in cell A1 and B1:
100 5%
75 10%
50 42%
30 30%
15 5%
0 8%
Thus, the formula would "randomly" return the number "15" 5% of all times.
Slightly less overhead:
Make a reference chart of your values, and a running total of probability:
C D E
100 5% 0
75 10% 5%
50 42% 15%
30 30% 57%
15 5% 87%
0 8% 92%
Then lookup a 0-1 random number on this chart. =LOOKUP(RAND(),$E$2:$E$7,$C$2:$C$7)
I generated 5224 numbers and produced this pivot chart of the results. Refreshing caused the percentages to waver a bit around the targets, but all attempts looked good.
Row Labels Count Percentage Target
0 421 8.06% 8%
15 262 5.02% 5%
30 1608 30.78% 30%
50 2160 41.35% 42%
75 490 9.38% 10%
100 283 5.42% 5%
Grand Total 5224 100.00%
Or you could do it with two cells and a long if statement:
=RAND()
=IF(A9<0.05,100,IF(A9<0.15,75, ... 0))...
This functionality comes as part of the analysis toolkit add in. You can find this in Excel options -> add ins -> manage add ins.
You want random number generation, and then pick the 'discrete' distribution. The input into this is the table you provided in your post.
"Discrete
Characterized by a value and the associated probability range. The range
must contain two columns: The left column contains values, and the right
column contains probabilities associated with the value in that row. The sum
of the probabilities must be 1."
jsarma's suggestion is also a good one....
You can use vlookup and randbetween.
You'll want to use randbetween. http://office.microsoft.com/en-us/excel-help/randbetween-HP005209230.aspx
vlookup: http://office.microsoft.com/en-us/excel-help/vlookup-HP005209335.aspx
Fill one column with consecutive numbers ranging from 1-100.
Fill another column with 5 100's, 10 75's, 42 50's, etc...
Now...
=VLOOKUP(RANDBETWEEN(1,100),A1:B100,2)
There's probably a better way to do this, but I tried this and it seems to work.

How to calculate growth with a positive and negative number?

I am trying to calculate percentage growth in excel with a positive and negative number.
This Year's value: 2434
Last Year's value: -2
formula I'm using is:
(This_Year - Last_Year) / Last_Year
=(2434 - -2) / -2
The problem is I get a negative result. Can an approximate growth number be calculated and if so how?
You could try shifting the number space upward so they both become positive.
To calculate a gain between any two positive or negative numbers, you're going to have to keep one foot in the magnitude-growth world and the other foot in the volume-growth world. You can lean to one side or the other depending on how you want the result gains to appear, and there are consequences to each choice.
Strategy
Create a shift equation that generates a positive number relative to the old and new numbers.
Add the custom shift to the old and new numbers to get new_shifted and old_shifted.
Take the (new_shifted - old_shifted) / old_shifted) calculation to get the gain.
For example:
old -> new
-50 -> 30 //Calculate a shift like (2*(50 + 30)) = 160
shifted_old -> shifted_new
110 -> 190
= (new-old)/old
= (190-110)/110 = 72.73%
How to choose a shift function
If your shift function shifts the numbers too far upward, like for example adding 10000 to each number, you always get a tiny growth/decline. But if the shift is just big enough to get both numbers into positive territory, you'll get wild swings in the growth/decline on edge cases. You'll need to dial in the shift function so it makes sense for your particular application. There is no totally correct solution to this problem, you must take the bitter with the sweet.
Add this to your excel to see how the numbers and gains move about:
shift function
old new abs_old abs_new 2*abs(old)+abs(new) shiftedold shiftednew gain
-50 30 50 30 160 110 190 72.73%
-50 40 50 40 180 130 220 69.23%
10 20 10 20 60 70 80 14.29%
10 30 10 30 80 90 110 22.22%
1 10 1 10 22 23 32 39.13%
1 20 1 20 42 43 62 44.19%
-10 10 10 10 40 30 50 66.67%
-10 20 10 20 60 50 80 60.00%
1 100 1 100 202 203 302 48.77%
1 1000 1 1000 2002 2003 3002 49.88%
The gain percentage is affected by the magnitude of the numbers. The numbers above are a bad example and result from a primitive shift function.
You have to ask yourself which critter has the most productive gain:
Evaluate the growth of critters A, B, C, and D:
A used to consume 0.01 units of energy and now consumes 10 units.
B used to consume 500 units and now consumes 700 units.
C used to consume -50 units (Producing units!) and now consumes 30 units.
D used to consume -0.01 units (Producing) and now consumes -30 units (producing).
In some ways arguments can be made that each critter is the biggest grower in their own way. Some people say B is best grower, others will say D is a bigger gain. You have to decide for yourself which is better.
The question becomes, can we map this intuitive feel of what we label as growth into a continuous function that tells us what humans tend to regard as "awesome growth" vs "mediocre growth".
Growth a mysterious thing
You then have to take into account that Critter B may have had a far more difficult time than critter D. Critter D may have far more prospects for it in the future than the others. It had an advantage! How do you measure the opportunity, difficulty, velocity and acceleration of growth? To be able to predict the future, you need to have an intuitive feel for what constitutes a "major home run" and a "lame advance in productivity".
The first and second derivatives of a function will give you the "velocity of growth" and "acceleration of growth". Learn about those in calculus, they are super important.
Which is growing more? A critter that is accelerating its growth minute by minute, or a critter that is decelerating its growth? What about high and low velocity and high/low rate of change? What about the notion of exhausting opportunities for growth. Cost benefit analysis and ability/inability to capitalize on opportunity. What about adversarial systems (where your success comes from another person's failure) and zero sum games?
There is exponential growth, liner growth. And unsustainable growth. Cost benefit analysis and fitting a curve to the data. The world is far queerer than we can suppose. Plotting a perfect line to the data does not tell you which data point comes next because of the black swan effect. I suggest all humans listen to this lecture on growth, the University of Colorado At Boulder gave a fantastic talk on growth, what it is, what it isn't, and how humans completely misunderstand it. http://www.youtube.com/watch?v=u5iFESMAU58
Fit a line to the temperature of heated water, once you think you've fit a curve, a black swan happens, and the water boils. This effect happens all throughout our universe, and your primitive function (new-old)/old is not going to help you.
Here is Java code that accomplishes most of the above notions in a neat package that suits my needs:
Critter growth - (a critter can be "radio waves", "beetles", "oil temprature", "stock options", anything).
public double evaluate_critter_growth_return_a_gain_percentage(
double old_value, double new_value) throws Exception{
double abs_old = Math.abs(old_value);
double abs_new = Math.abs(new_value);
//This is your shift function, fool around with it and see how
//It changes. Have a full battery of unit tests though before you fiddle.
double biggest_absolute_value = (Math.max(abs_old, abs_new)+1)*2;
if (new_value <= 0 || old_value <= 0){
new_value = new_value + (biggest_absolute_value+1);
old_value = old_value + (biggest_absolute_value+1);
}
if (old_value == 0 || new_value == 0){
old_value+=1;
new_value+=1;
}
if (old_value <= 0)
throw new Exception("This should never happen.");
if (new_value <= 0)
throw new Exception("This should never happen.");
return (new_value - old_value) / old_value;
}
Result
It behaves kind-of sort-of like humans have an instinctual feel for critter growth. When our bank account goes from -9000 to -3000, we say that is better growth than when the account goes from 1000 to 2000.
1->2 (1.0) should be bigger than 1->1 (0.0)
1->2 (1.0) should be smaller than 1->4 (3.0)
0->1 (0.2) should be smaller than 1->3 (2.0)
-5-> -3 (0.25) should be smaller than -5->-1 (0.5)
-5->1 (0.75) should be smaller than -5->5 (1.25)
100->200 (1.0) should be the same as 10->20 (1.0)
-10->1 (0.84) should be smaller than -20->1 (0.91)
-10->10 (1.53) should be smaller than -20->20 (1.73)
-200->200 should not be in outer space (say more than 500%):(1.97)
handle edge case 1-> -4: (-0.41)
1-> -4: (-0.42) should be bigger than 1-> -9:(-0.45)
Simplest solution is the following:
=(NEW/OLD-1)*SIGN(OLD)
The SIGN() function will result in -1 if the value is negative and 1 if the value is positive. So multiplying by that will conditionally invert the result if the previous value is negative.
Percentage growth is not a meaningful measure when the base is less than 0 and the current figure is greater than 0:
Yr 1 Yr 2 % Change (abs val base)
-1 10 %1100
-10 10 %200
The above calc reveals the weakness in this measure- if the base year is negative and current is positive, result is N/A
It is true that this calculation does not make sense in a strict mathematical perspective, however if we are checking financial data it is still a useful metric. The formula could be the following:
if(lastyear>0,(thisyear/lastyear-1),((thisyear+abs(lastyear)/abs(lastyear))
let's verify the formula empirically with simple numbers:
thisyear=50 lastyear=25 growth=100% makes sense
thisyear=25 lastyear=50 growth=-50% makes sense
thisyear=-25 lastyear=25 growth=-200% makes sense
thisyear=50 lastyear=-25 growth=300% makes sense
thisyear=-50 lastyear=-25 growth=-100% makes sense
thisyear=-25 lastyear=-50 growth=50% makes sense
again, it might not be mathematically correct, but if you need meaningful numbers (maybe to plug them in graphs or other formulas) it's a good alternative to N/A, especially when using N/A could screw all subsequent calculations.
You should be getting a negative result - you are dividing by a negative number. If last year was negative, then you had negative growth. You can avoid this anomaly by dividing by Abs(Last Year)
Let me draw the scenario.
From: -303 To 183, what is the percentage change?
-303, -100% 0 183, 60.396% 303, 100%
|_________________ ||||||||||||||||||||||||________|
(183 - -303) / |-303| * 100 = 160.396%
Total Percent Change is approximately 160%
Note: No matter how negative the value is, it is treated as -100%.
The best way to solve this issue is using the formula to calculate a slope:
(y1-y2/x1-x2)
*define x1 as the first moment, so value will be "C4=1"
define x2 as the first moment, so value will be "C5=2"
In order to get the correct percentage growth we can follow this order:
=(((B4-B5)/(C4-C5))/ABS(B4))*100
Perfectly Works!
Simplest method is the one I would use.
=(ThisYear - LastYear)/(ABS(LastYear))
However it only works in certain situations. With certain values the results will be inverted.
It really does not make sense to shift both into the positive, if you want a growth value that is comparable with the normal growth as result of both positive numbers. If I want to see the growth of 2 positive numbers, I don't want the shifting.
It makes however sense to invert the growth for 2 negative numbers. -1 to -2 is mathematically a growth of 100%, but that feels as something positive, and in fact, the result is a decline.
So, I have following function, allowing to invert the growth for 2 negative numbers:
setGrowth(Quantity q1, Quantity q2, boolean fromPositiveBase) {
if (q1.getValue().equals(q2.getValue()))
setValue(0.0F);
else if (q1.getValue() <= 0 ^ q2.getValue() <= 0) // growth makes no sense
setNaN();
else if (q1.getValue() < 0 && q2.getValue() < 0) // both negative, option to invert
setValue((q2.getValue() - q1.getValue()) / ((fromPositiveBase? -1: 1) * q1.getValue()));
else // both positive
setValue((q2.getValue() - q1.getValue()) / q1.getValue());
}
These questions are answering the question of "how should I?" without considering the question "should I?" A change in the value of a variable that takes positive and negative values is fairly meaning less, statistically speaking. The suggestion to "shift" might work well for some variables (e.g. temperature which can be shifted to a kelvin scale or something to take care of the problem) but very poorly for others, where negativity has a precise implication for direction. For example net income or losses. Operating at a loss (negative income) has a precise meaning in this context, and moving from -50 to 30 is not in any way the same for this context as moving from 110 to 190, as a previous post suggests. These percentage changes should most likely be reported as "NA".
Just change the divider to an absolute number.i.e.
A B C D
1 25,000 50,000 75,000 200%
2 (25,000) 50,000 25,000 200%
The formula in D2 is: =(C2-A2)/ABS(A2) compare with the all positive row the result is the same (when the absolute base number is the same). Without the ABS in the formula the result will be -200%.
Franco
Use this code:
=IFERROR((This Year/Last Year)-1,IF(AND(D2=0,E2=0),0,1))
The first part of this code iferror gets rid of the N/A issues when there is a negative or a 0 value. It does this by looking at the values in e2 and d2 and makes sure they are not both 0. If they are both 0 then it will place a 0%. If only one of the cells are a 0 then it will place 100% or -100% depending on where the 0 value falls. The second part of this code (e2/d2)-1 is the same code as (this year - lastyear)/Last year
Please click here for example picture
I was fumbling for answers today, and think this would work...
=IF(C5=0, B5/1, IF(C5<0, (B5+ABS(C5)/1), IF(C5>0, (B5/C5)-1)))
C5 = Last Year, B5 = This Year
We have 3 IF statements in the cell.
IF Last Year is 0, then This Year divided by 1
IF Last Year is less than 0, then This Year + ABSolute value of Last Year divided by 1
IF Last Year is greater than 0, then This Year divided by Last Year minus 1
Use this formula:
=100% + (Year 2/Year 1)
The logic is that you recover 100% of the negative in year 1 (hence the initial 100%) plus any excess will be a ratio against year 1.
Short one:
=IF(D2>C2, ABS((D2-C2)/C2), -1*ABS((D2-C2)/C2))
or confusing one (my first attempt):
=IF(D2>C2, IF(C2>0, (D2-C2)/C2, (D2-C2)/ABS(C2)), IF(OR(D2>0,C2>0), (D2-C2)/C2, IF(AND(D2<0, C2<0), (D2-C2)/ABS(C2), 0)))
D2 is this year, C2 is last year.
Formula should be this one:
=(thisYear+IF(LastYear<0,ABS(LastYear),0))/ABS(LastYear)-100%
The IF value if < 0 is added to your Thisyear value to generate the real difference.
If > 0, the LastYear value is 0
Seems to work in different scenarios checked
This article offers a detailed explanation for why the (b - a)/ABS(a) formula makes sense. It is counter-intuitive at first, but once you play with the underlying arithmetic, it starts to make sense. As you get used to it eventually, it changes the way you look at percentages.
Aim is to get increase rate.
Idea is following:
At first calculate value of absolute increase.
Then value of absolute increase add to both, this and last year values. And then calculate increase rate, based on the new values.
For example:
LastYear | ThisYear | AbsoluteIncrease | LastYear01 | ThisYear01 | Rate
-10 | 20 | 30 = (10+20) | 20=(-10+30)| 50=(20+30) | 2.5=50/20
-20 | 20 | 40 = (20+20) | 20=(-20+40)| 60=(20+40) | 3=60/2
=(This Year - Last Year) / (ABS(Last Year))
This only works reliably if this year and last year are always positive numbers.
For example last_year=-50 this_year = -1. You get -100% growth when in fact the numbers have improved a great deal.

Resources