I have the situation of the picture
.
A table and two data: a rating value and another value. I need to look up to the matrix along the right row based on the current rating and sweep horizontally based on the input value and get the nearest smaller rating.
So in this case, I'm expecting 2. If the rating were 2, then results should be 3 and with 3, then 2.
Try this formula:
=INDEX(B1:D1,MATCH(B7,INDEX(B2:D4,MATCH(B6,A2:A4,0),0)))
The inner INDEX/MATCH sets the proper range. While the outer finds the first time that the value number is equal to or less than and the next is greater than.
EDIT: As per the OP's comment
If you want the next column just add one:
=INDEX(B1:D1,IFERROR(MATCH(B7,INDEX(B2:D4,MATCH(B6,A2:A4,0),0))+1,1))
The IFERROR deals with the times that the value is less than the first number in the series.
Related
Here is an example of the data I'm trying to organize:
I'm looking for a way to automatically see the top 3 categories (column) for each Name# (row). The size of the category is determined by the number below the category.
Ideally, I'd also like to see a percentage breakdown (from the total) for each category. For example, in row "Name3" 2 categories make up a significantly larger portion of the total values. However, without this percentage breakdown, the 3 top values would seem to be comparable, when they are in fact, not.
Interested to see how this would all work with duplicate numbers, too.
I've tried Excel's rank function, but this doesn't tell me the categories that have the 3 largest sizes, just the 3 highest values.
With Office 365:
=FILTER(SORTBY($B$1:$H$1,B2:H2,-1),SORT(B2:H2,1,-1,TRUE)>=LARGE(B2:H2,3))
And copy down.
If there are ties it will expand the results to include it. It finds the third highest value and returns everything that is equal to or greater than it.
This approach spills all the results at once (array version). In cell J2, you can put the following formula:
=LET(D, A1:H5, A, TAKE(D,,1), DROP(REDUCE("", DROP(A,1), LAMBDA(ac,aa,
VSTACK(ac, TAKE(SORT(DROP(FILTER(D, (A=aa) + (A="")),,1),2,-1,1),1,3)))),1))
It assumes as per input data the cell A1 is empty (if not it can be adjusted accordingly). Here is the output:
An alternative that doesn't require previous assumption (but it is not really a hard one) is the following:
=LET(names, A2:A5, Data, B2:H5, colors, B1:H1, DROP(REDUCE("", names,
LAMBDA(ac,n, VSTACK(ac, TAKE(SORT(VSTACK(colors, INDEX(Data, XMATCH(n,names),0))
,2,-1,TRUE),1,3)))),1))
The non-array version can be obtained from previous approach, and expand it down:
=TAKE(SORT(VSTACK($B$1:$H$1,INDEX($B$2:$H$5, XMATCH(A2,$A$2:$A$5),0)),2,-1,TRUE),1,3)
Explanation
To spill the entire solution it uses DROP/REDUCE/VSTACK pattern. Check my answer to the following question: how to transform a table in Excel from vertical to horizontal but with different length.
For the first formula we filter for a given element of A name (aa) via FILTER the input data (D) to select rows where the name is empty (to consider the header) OR (plus (+) condition) the name is equal to aa. We remove via DROP the first column of the filter result (names column). Next we SORT by the second row (the first rows are the colors) in descending order (-1) by column (last input parameter of SORT we can use TRUE or 1). Finally, we use TAKE to take the first three columns and the first row.
For the second approach, we select the values for a given row (names equals n) and use INDEX to select the entire row (column index 0), then we form an array via VSTACK to add as first row the colors and use the similar logic as in previous approach for sorting and select the corresponding rows and column (colors).
Notes:
If you don't have VSTACK function available, then you can replace it as follow: CHOOSE({1;2}, arr1,arr2) and substitute arr1, arr2, wit the corresponding arrays.
In the second formula instead of INDEX/XMATCH you can use: DROP(FILTER(Data, names=n),,1), it is a matter of personal preference.
I hope you are will be fine.
I am stuck in finding the ranks of students based on percentage.
I have Excel table having multiple columns, concerning columns are Percentage and Position. My data set starts from Row 25 = R25(in excel)
I am using following formula to calculate the percentage of the students based on obtained marks and total marks
=IF(V25="F","",N25/O25)
Where Column V includes pass or fail (in case of fail "F"), column N includes obtained marks and column O includes total marks
It produces the correct output as required:
Now comes to the real problem. Finding the rank/position of student.
I am using RANK.EQ formula to calculate the rank/position of the students based on percentage
=IF(V25="F","Nil",RANK.EQ(P25,[Percentage]))
It also produces the correct output as per formula:
complete pic = >
Now what I want
The two student who obtains 80% marks are ranked as 1 (according to data set)
Now the student who obtains 74% marks should be ranked as 2 instead of 3 and so on
Here is the clear picture of what I require:
I already tried the =SUMPRODUCT(), =MATCH(), =COUNTIF() etc.
Got something I hope you can adapt to your needs. I replied your data this way:
As you can see, formula in column B returns ranking as you wish. To get this,I used an array formula:
=IF(A1="";"";SUM(IF(FREQUENCY(IF($A$1:$A$6>A1;$A$1:$A$6);$A$1:$A$6)>0;1))+1)
NOTE: Because this in an array formula, it must be entered into cell pressing CTRL+ENTER+SHIFT or it
won't work! You will know if you did it properly if your formula shows { at start and } at end.
The trick here is you want to rank your data in descendant order, but excluding duplicates. The array formula first gets an array of values higher than criteria (number in row), and then count how many unique values are in that array. If 0, it means is the highest value, so its rank is 1 (that explains the +1 at end of formula). If count returns 1, means there is an unique value higher than criteria. so its rank is 2 (count of 1 + we add 1 = 2), and so on...
Hope you can adapt this to your needs.
For this I used info shown here:
Count unique values among duplicates
I am trying to use index match functions to determine the appropriate rate for the below table.
So for example a consumer loan that is for a person that owns property, the car is 2 years or less in age and the total loan to value ratio is less than 140% should return a value of 5.15%
I believe this is what you wanted...
I would use a series of nested if functions to evaluate which column of LTV I would want the value to come from.
"That is what is done in the AND( ) part. If the value is greater than the 110% and smaller than 140% let's do the Index Match on the 110% Column, Otherwise do it on the 140% Column."
You could extend this for more columns with more IFs in the false condition.
Then it is a simple INDEX match with concatenation. It searches for the three parameters all concatenated in a single range of concatenations.
Hope it helped.
Proof of Concept
In order to achieve the above I had to make a minor edit to your header to be able to distinguish between the two 140% columns.
The functions used in this answer are:
AGGREGATE function
MATCH function
INDEX function
ROW function
IFERROR function
I placed the main part of the formula inside the IFERROR function as a way of dealing with things that may be out of range or when not all the input have been provided. I then assumed that what you were basing your search on would be provided in a series of cells. In my example I assumed the questions would be asked in the range H3 to K3 and I place the results in L3.
The main concept is centered around the INDEX function. I specified the index range as being the height of your table and the width of the percentage rates. Or for this example D2:F9.
=IFERROR(INDEX($D$2:$F$9,row number, column number),"Not Found")
That is the easy part. That more challenging part is determining the row and column number to look in. Lets start with the column number as it is the slightly easier of the two. I assumed the ratio to look for, or rather the header of the column to look in would be supplied. I basically used this equation to determine the column number:
=MATCH(K3,$D$1:$F$1,0)
which in layman's terms is which column between D and F, counting column D as 1, has the value equal to the contents of K3. So now that there is a formula to determine the column, we can drop that into our original formula and wind up with:
=IFERROR(INDEX($D$2:$F$9,row number,MATCH(K3,$D$1:$F$1,0)),"Not Found")
Now we just need to determine the row number. This is the most complex operation. We are going to basically make a bunch of logical checks and take the first row that matches all the logical checks. The premise here is that a logical check is either TRUE or FALSE. In excel 0 is false an every other integer is TRUE. So if we multiply a series of logical checks together, only the one that is true in all cases will be equal to 1. The first logical check is the loan type. it will be followed by the living status and then the vehicle age.
=(H3=$A$2:$A$9)*(I3=$B$2:$B$9)*(J3=C2:C9)
now if you put that into an array formula you will get a series of true false or 1/0. We are going to use it inside an AGGREGATE function with a special feature. The AGGREGATE function will perform array like calculation for some of its functions. We are going to use function 15 which will do this. We are also going to tell the aggregate function to ignore all errors, which is what the 6 does. So in the end what we wind up doing is dividing each row number by the logical check. If the logical check is false or 0, it will generate a Div/0! error which aggregate will choose to ignore. In the end we wind up with a list of row which match our logical check. We then tell the aggregate that we want the first result with the ,1. so we wind up with a formula that looks like:
=AGGREGATE(15,6,ROW($A$2:$A$9)/((H3=$A$2:$A$9)*(I3=$B$2:$B$9)*(J3=C2:C9)),1)
While this does provide us with the row number we want, we need to adjust it to make it an index number. In order to do this you need to subtract the number of header rows. In this case 1. So the index row number is given by this formula:
=AGGREGATE(15,6,ROW($A$2:$A$9)/((H3=$A$2:$A$9)*(I3=$B$2:$B$9)*(J3=C2:C9)),1)-1
And when we substitute that back into the earlier equation for the row number, we wind up with the final equation of:
=IFERROR(INDEX($D$2:$F$9,AGGREGATE(15,6,ROW($A$2:$A$9)/((H3=$A$2:$A$9)*(I3=$B$2:$B$9)*(J3=C2:C9)),1)-1,MATCH(K3,$D$1:$F$1,0)),"Not Found")
As seen in the picture I have 5 sets of 2's in one column.
I would like it so that each set is in its own column.
Is there a way to do that?
I tried text to columns, but it did not work.
General solution
Imagine I have a vertical array starting in cell B2, which I want to separate into N stacked columns. I will place these columns from cell E4, as the picture indicates.
The code which achieves what I want is:
+OFFSET($B$2,(ROW()-ROW($E$4))*N+(COLUMN()-COLUMN($E$4)),0)
Replace N with your desired number (and the origin and destination cell with your particular values, B2 and E4 in this example), and expand the formula vertically and horizontally to form your desired matrix of N columns. For the case of N=3, you get:
(PS: if your array is horizontal, use transpose to transform to vertical. You can then transpose the resulting matrix, to get the final result.)
Explanation
The logic is simple. The function OFFSET has three compulsory inputs. The first one is the first point of your array you want to transform (in the example above, $B$2. The point you select has an index of 0, the one below an index of 1, etc. So, what you want is to put these ordered index into a matrix form, as shown below (for the case of N=3):
The rule to move these indexes is given in the second entry of the OFFSET function. This is basically a formula that calculates a sequence 0, 1, 2, 3 ... using some fixed values (the number of the row and columns of the first cell where you are putting the result, ROW($E$4) and COLUMN($E$4), which are equal to 4 and 5 respectively), and the variable values of the cell where you are placing the number (ROW() and COLUMN()). The formula computes the difference between actual row and reference row number, scale it by N, and adds any difference between actual and reference column. This formula gives the desired series 0, 1, 2, 3... for our desired output matrix.
Finally, the last item of OFFSET is equal to zero, since we are transforming with a vertical column of data, so no horizontal offset is needed.
You can do it with e.g. formula; enter this to C1 and fill down and right:
=OFFSET($A$1,ROW()-1+(COLUMN()-3)*6,0)
Take the total cells, dived it by 3 and cut and paste. I wasted a 30 mins trying all the solutions offered out there.
I gave up and now my project is complete. Only took about 15 seconds.
To split one column into multiple columns with column first order, in other words, without transpose, we can modify the formula as shown in https://www.extendoffice.com/documents/excel/3132-excel-convert-vector-to-matrix.html, which is the solution for row first order, i.e., with transpose, exchange the roles of ROW() and COLUMN(), example code:
=OFFSET($A$1:$A$10494,ROW()-ROW($B$1)+((COLUMN()-COLUMN($B$1))*(ROWS($A$1:$A$10494)/18)),0,1,1)
Here $a1:$a$10494 is source, $b$1 is destination, 18 is columns numbers to split into.
This can be used to get back the table structure of %debug print output in pdb, for example, which will split the output into narrow bands.
I have an array in excel: C2:C20. I want to find the cell with the median and then find the value of a cell in column A corresponding to the row. Some of the cells in the array might not contain anything. How do I do that?
EDIT:
The table is about observations.
The A column is about the name of the observation.
Sorry for the Danish language.
Hyppighed = frequency
Summeret hyppighed = summerized frequency
Sample table:
Result table when using the suggested functions
This will return the first median value found in C2:C20 and return the corresponding cell in column A.
=INDEX(A2:A20,MATCH(MEDIAN(C2:C20),C2:C20,0),1)
If you know exactly what you are looking for you can replace MEDIAN(C2:C20) with whatever you are searching in the Array contained in column C. If it is a string you are searching use "" around your text.
EDIT:
The reason you are getting N/A with your data set is because there is no exact match to the Median. In order to resolve this you need to replace the 0 with a 1 if you want a value higher than or equal the median or -1 if you want a value lower than or equal to the median.
Try this and it will give you the next highest median value if there is no match.
=INDEX(A2:A20,MATCH(MEDIAN(C2:C20),C2:C20,1),1)
For the purposes of doing an index look up the above method using the median function is inferior,
barry houdini made a great suggestion below which will choose the median value available or the next lowest one regardless of sorting...
=INDEX(A2:A20,MATCH(SMALL(C2:C20,INT((COUNT(C2:C20)+1)/2)),C2:C20,0))
or alternatively if you wanted to choose the highest one if the median is not available rather than the lowest one you could do
=INDEX(A2:A20,MATCH(LARGE(C2:C20,INT((COUNT(C2:C20)+1)/2)),C2:C20,0))