I have this table in excel
I want to create a new column where if have a total score let's say of 92 I do an index/match on the table and get it.
I tried this
=INDEX('Risk Assessment Matrix '!I24:I28,1,1,MATCH(111,'Risk Assessment Matrix '!J24:J28,0))
but not working.
Any help please?
Thanks,
Ilias
Assuming a value given is not above 140, you don't even need a 3rd column. Try:
Formula in D2:
=INDEX(A1:A5,MATCH(D1,B1:B5,-1))
If D1 happens to be above 140 an error is returned. You can catch that by nesting the above in =IFERROR(<TheAbove>,"No Match") for example.
Reorder the list so the third column is ascending not descending. and change the >=0 to just 0
Then use:
=INDEX('Risk Assessment Matrix '!I24:I28,MATCH(111,'Risk Assessment Matrix '!K24:K28))
Your INDEX/MATCH looks a bit odd. You wouldn't normally have the "1,1," in there.
Try this:
=INDEX('Risk Assessment Matrix '!I24:I28, MATCH(111,'Risk Assessment Matrix '!J24:J28,0))
This should return "High" (assuming your first column in the table is "I".
Two methods shown:
Pay attention to the order.
An alternate option is the use the new XLOOKUP function.
Although it would require changing the minimum value range from 0 to -9999. An out of range value for non-numeric values of 9999 would also need to be added.
It has the advantage of being easier to read compared to INDEX and MATCH.
=XLOOKUP($D2,$B$2:$B$6,$A$2:$A$6,"Not Found",-1)
The formula looks up the value against a single list of minimum values.
The match_mode (last parameter) is set to -1. This means perform an exact match and if nothing is found return the next smaller item.
Related
I am trying to calculate a running average on a filtered data table. All other posts online use Sumproduct(Subtotal) on the entire range but do not calculate a row by row running average
I am stuck on how to calculate columns C and D.
If column B (Score) > 0, I want to sum and average it under column C (Average Win)
If column B (Score) < 0, I want to sum and average it under column D (Average Loss)
The table is filterable by column A (Type) and the results should look as follows
Progress so far:
I have figured out how to calculate a Cumulative score based on filtered data. However this does not fully solve my problem. I appreciate any help!
=SUBTOTAL(3,B3)*SUBTOTAL(9,B$3:B3)
SUBTOTAL(3,B3) checks if the current row is visible, SUBTOTAL(9,B$3:b3) sums the values.
Final update needed
Jos - Thank you for your detailed explanation on how subtotal() works. I learned a ton through your explanation and will continue to study it. This is my first time being exposed to structured referencing so some of the syntax is a bit confusing to me still
The last formula I need is a running win % column where a Win is defined by score > 0. Please see the picture below
My assumptions believe that the same formula would work, except that we average a 1 or 0 in each row instead of the [Score] column.
Using the prior solution, why can't we modify the output of your prior solution to calculate a running win %?
[...] IF([Score]>0,IF(ROW([Score])<=ROW([#Score]),[Win])))),0)
Where [Win] is a helper column with the outputs 1 for win, 0 for loss.
This could be done by saying
if([#score]>0,1,0)
Instead of averaging out the actual #Score, this would average out a column of 1's and 0's with the desired output 0%, 50%, 66%, etc.
I am aware that the solution I provided does not work but I am trying to embrace the correct logic. I still struggle to understand how these structured column references are calculated on a row by row basis.
For example: Average(If([Score]>0,[Score])
How is this calculated on a row by row basis? When A3 does If([Score] > 0,), does this equal If({-10}>0)? When on A4, does If([Score]>0) equal If({-10,20} >0)? Thank you for your patience and help thus far.
I disagree with your result for Average Loss for the last row of your unfiltered table (surely -9.33...?), but try this for Average Win:
=IFERROR(AVERAGE(IF(SUBTOTAL(3,OFFSET(INDEX([Score],1),ROW([Score])-MIN(ROW([Score])),)),IF([Score]>0,IF(ROW([Score])<=ROW([#Score]),[Score])))),0)
Same formula for Average Loss, changing [Score]>0 to [Score]<0.
Explanation:
Using the data you provided and assuming:
The table's top-left cell is in A1
The table is filtered on the Type column for "A"
In order to determine which rows are filtered, we must pass an array of range references - i.e. for each cell within a chosen column of the table - to the SUBTOTAL function. It's a touch unfortunate that such an array of range references can only be generated via a volatile function (INDIRECT or OFFSET), but here, unless we resort to helper columns, we are left with no choice.
INDEX([Score],1)
simply returns a range reference to the first cell within the Score column. When using Excel tables, it's preferable not to write formulas which include a mixture of structured and non-structured referencing, even if that results in slightly longer expressions. So here, for example, we would not reference A2 within the formula.
ROW([Score])-MIN(ROW([Score]))
generates an array of integers from 0 up to one fewer than the number of rows in the table, i.e.
{0;1;2;3;4}
and so
=IFERROR(AVERAGE(IF(SUBTOTAL(3,OFFSET(INDEX([Score],1),ROW([Score])-MIN(ROW([Score])),)),IF([Score]>0,IF(ROW([Score])<=ROW([#Score]),[Score])))),0)
becomes
=IFERROR(AVERAGE(IF(SUBTOTAL(3,OFFSET(A2,{0;1;2;3;4},)),IF([Score]>0,IF(ROW([Score])<=ROW([#Score]),[Score])))),0)
OFFSET then generates an array of range references (though note that you will not be able to 'see' this step within the Evaluate Formula window - rather, an array of #VALUE! errors is displayed):
=IFERROR(AVERAGE(IF(SUBTOTAL(3,{A2;A3;A4;A5;A6}),IF([Score]>0,IF(ROW([Score])<=ROW([#Score]),[Score])))),0)
SUBTOTAL then determines which of these range references is filtered (note that care must be given here to the choice of first parameter), returning the relevant Boolean, so that:
SUBTOTAL(3,{A2;A3;A4;A5;A6})
resolves to:
{1;1;1;0;1}
And so we now have:
=IFERROR(AVERAGE(IF({1;1;1;0;1},IF([Score]>0,IF(ROW([Score])<=ROW([#Score]),[Score])))),0)
and the rest is straightforward.
So, I would use averageifs().
=averageifs(B:B,B:B,">=1",A:A,"A")
is one example, note I have added the control of Type A in the example.
See:
I have a Vlookup with a Match. The Vlookup looks for a country and the match looks for a weight. Each weight for different countries has a different cost.
My formula seems to return the result to the left of what I would expect. So 65kg is returning the cost of 60kg.
This is the code that I have used. I have tried including 1+ in front of D9. I have had False as 0 and I have tried changing the 0's to 1 and -1.
"=VLOOKUP(D8,Express!C2:AU128,MATCH(D9,Express!D3:AU3,0),FALSE)"
Hope this makes sense.
Thank you for any help.
Match returns the relative position in the range. so the fact that the third criterion in the VLOOKUP is 1 based not 0 based you need to start the range in the MATCH with the same column as in the VLOOKUP:
Change Express!D3:AU3 to Express!C3:AU3
=VLOOKUP(D8,Express!C2:AU128,MATCH(D9,Express!C3:AU3,0),FALSE)
Try this formula:
=VLOOKUP(D8,Express!C2:AU128,MATCH(D9,Express!D3:AU3,0)+1,FALSE)
I have a data array with column and row headers, I want to sort the rows in the array starting from the lowest value by concatenating the value with the column header name (tag). e.g
Array example here
Now noticed the sort requirement, so edited to this:
Which does what is expected almost as it has problems with duplicate values, but I don't think it will be the best solution if you have the amount of data you mention in your comment.
Came up with this, using index() and match(), look at the second version :
Double lookups (where you need to locate a value in orderm to find the position of a related lookup which returns the desired result) can be complicate to write but are not necessarily taxing on calculation cycles.
Per your sample image, put this in B7 then drag right and down.
=INDEX($B$2:$E$2, AGGREGATE(15, 7, COLUMN($A:$D)/(INDEX($B$3:$E$4,MATCH($A7,$A$3:$A$4,0), 0)=SMALL(INDEX($B$3:$E$4,MATCH($A7,$A$3:$A$4,0), 0),COLUMN(A:A))), COUNTIF($A7:A7, "* "&SMALL(INDEX($B$3:$E$4,MATCH($A7,$A$3:$A$4,0), 0),COLUMN(A:A)))+1))&" "&SMALL(INDEX($B$3:$E$4,MATCH($A7,$A$3:$A$4,0), 0),COLUMN(A:A))
I'm having an issue with INDEX + MATCH combination:
=INDEX(ALL!$C$1:$I$1,MATCH(TRUE,ALL!C2:I2<>0,0))
At the moment the aforementioned formula does this job to an extent, where if it finds <>0 value in a row it will return header from this specific column. The issue is that the ROW (as above C2:I2) needs to be specified.
I need to vlookup values in the column "A" in sheet "ALL" and based on that, look at corresponding rows between C:I and if the value in that specific row is <>0 then return heading value.
So, in green I would need a formula to pick up numbers from "Data Source" headings, based on value 1 or any value <>0. I'm guessing it all leads somehow to some sort of "vlookup" hybrid.
Any ideas how to combine vlookup in it?
Thanks
If there can only be one '1' per row, I was thinking of this
=SUMIF(INDEX(B:E,MATCH(G2,A:A,0),0),">0",$B$1:$E$1)
Otherwise if there can be more than one '1'
=INDEX($B$1:$E$1,MATCH(TRUE,INDEX(B:E,MATCH(G2,A:A,0),0)>0,0))
to match the first value greater than zero, in this case entered as an array formula.
A simple =SUMIF() formula will do, no other convoluted INDEX() and MATCH() nested formulas required.
Let's presume we have a data-table that starts at B2 and end at
F6, like this:
So now, to comprehend the solution, here's the syntax of SUMIF() formula (Function):
=SUMIF( range, criteria, [sum_range] )
So, what we want to do is:
go over the range of C3:F3 (and each other respective row)
the criteria to when to sum, is when this range contains 1
and we want to sum_range (sum up) fixed array of numbers, so $C$2:$F$2
So the result is (for row 3):
=SUMIF(C3:F3,1,$C$2:$F$2)
and we drag the formula down, producing expected result:
PS: I think this illustrates the point very well, as to why it's important to declare not only what your formula is doing but also, what you're trying to as in whole as there often is a better (easier) way to implement something, that you might not have thought of.
In other words, follow the Minimal, Complete and Verifiable Example
I have the data table below, and I want that given a value 'x' look in 'A' and get the lower value in 'B'.
For instance 10.000 should return 0, 38.000 should return 7,8 and 900.000 should return 20. In my locale '.' means thousand separator and ',' is for decimals.
If possible I would like a formula which works in excel and gdocs. Thanks.
A B
0 0
37.500,01 7,8
45.000,01 9,1
58.345,62 11,4
120.206,02 13,6
208.075,91 15,7
295.242,83 17,2
382.409,77 18,2
600.000,01 20
I don't know about gdocs but in excel try the following.
=vlookup(value ; $A$1:$B$9 ; 2 ; 1)
where value is the value you are searching for.
The only prerequisite is that column A must be sorted in ascending order, as you have in your example.
You can use LOOKUP function, assuming lookup value in C2 use this formula in D2
=LOOKUP(C2,A$1:B$9)
The following would work for your needs:
=INDEX(B:B,MATCH(38,A:A,1),1)
Where 38 is the value we are looking up. Match will look in A:A and return the row where the value is less than 38 (because the third parameter of the match() formula is 1).
The Index will return the row in B:B that Match() just outputted.
If you search for 900,000 you're hoping to return the value from 600,000.01, because that's the last value it is higher than.
You can do this with an array formula, but I prefer to make Index do that work for me. As such, I present INDEX/MATCH/INDEX:
First, sort your data in A Largest to Smallest.
=INDEX($B$1:$B$9,MATCH(TRUE,INDEX(900000>$A$1:$A$9,0),0))
You can change 900,000 to whichever number you're looking for, or reference a cell with the value in it.
The second INDEX, the one nested in there, is examining each cell in Col A to determine if your target value is greater than them. It creates an array of TRUE's and FALSE's.
Next, you use MATCH to find the first TRUE in that array you created. That's the position of the first cell that your target is greater than (this is why we sort largest to smallest).
Once we know how far down the list it is, we use the first INDEX to look that far down Col B and grab the info you're looking for!
Play around with it, it makes sense once you think your way through it :) Good luck!