Google Sheets: Dense Ranking from sorted values - google-sheets

I have a simple table with 3 columns:
[Name] [Score] [Rank]
For the 3rd column, I'm using the following formula to rank each row according to the score:
=RANK(C9,$C$9:$C$28,0)
The problem is that the formula isn't returning the values I'd expect. For example on the last row it returns 19 when it should be 5.
I found other formulas for ranking (RANK.EQ, etc.) but same issue happens.
Here is the Google Sheet to see it in context:
https://docs.google.com/spreadsheets/d/1P1m7UHPPIcQLQkzpnk-SI1y7-0mhKytCWDjA6FJzFrM/edit?usp=sharing
Any guidance appreciated

The results you want can be achieved with a simple MATCH formula:
=match(round(C9,0),NamedRange1,0)
Provided an array (named NamedRange1 for above) is created, say with:
=sort(unique(round(C9:C28,0)),1,0)

I think the result is as intended. Check this Ranking Wikipedia page (called 'standard competition ranking'). It says:
Standard competition ranking ("1224" ranking)
In competition ranking, items that compare equal receive the same
ranking number, and then a gap is left in the ranking numbers. The
number of ranking numbers that are left out in this gap is one less
than the number of items that compared equal. Equivalently, each
item's ranking number is 1 plus the number of items ranked above it.
This ranking strategy is frequently adopted for competitions, as it
means that if two (or more) competitors tie for a position in the
ranking, the position of all those ranked below them is unaffected
(i.e., a competitor only comes second if exactly one person scores
better than them, third if exactly two people score better than them,
fourth if exactly three people score better than them, etc.).
Thus if A ranks ahead of B and C (which compare equal) which are both
ranked ahead of D, then A gets ranking number 1 ("first"), B gets
ranking number 2 ("joint second"), C also gets ranking number 2
("joint second") and D gets ranking number 4 ("fourth").
What you want is 'dense ranking' and it can be achieved by pnuts's answer or something like this:
set G9 to 1
set G10 to =if(round(C10,0)<round(C9,0), G9+1, G9)
copy G10 and paste it into G11:G28
Sample sheet is here.

Thanks to #pnuts and #sangboklee for your solutions. I think I have a good solution now. It is pnuts's solution, just simplified:
=match(round($C9,0),sort(unique(round($C$9:$C$28,0)),1,false),0)
This essentially "embeds" the created array within a single formula, that can be applied to all rows. And as a bonus, the values don't even have to be sorted.
Please check for correctness folks, but I think this works. I've updated the linked Google Sheet from the original question description (it's "Solution 2b").

Related

Want to rank players for each session based on number of wins, games, and then points

I want to automatically decide who's 1st, 2nd, 3rd, and 4th for each session. I want it to be decided based on the number of match wins first, then game wins if matches are equal, and then points if games are equal. If everything is equal, then have 2 players as the same position and the next one skipped (1st, 2nd, 2nd, and 4th). The highlighted cells are where I want to calculate this. Can someone please help me with this?
Sample file:
https://docs.google.com/spreadsheets/d/1Ry3BAqXF4Di5lHGlY_roDyzQz7FmTaP1XvhO6Psm4sU/edit#gid=0
I have looked online for something, but have been unsuccessful in finding a formula for 3 columns.
I don't think there's an exact formula for this. Obviously SORT or SORTN would correctly sort them, but not return ranking with equals. What I thought of is to MAP the ranking of each column's values giving and sum them, but with different "weight". *100 to the first, *10 to the second, and *1 to the third:
=MAP(B2:B5, C2:C5, D2:D5, LAMBDA(a,b,c,RANK(a,B2:B5)*100+RANK(b,C2:C5)*10+RANK(c,D2:D5)*1))
That returns something like this:
Then wrapped it in LAMBDA in order to be used as the new source of RANKING, and calculated it with the help of BYROW. But now the ranking needs to be done in reversed order. The greater values are going to equal to the ones at the bottomo of the ranking and vice versa. That's why the 0 in RANK(e,r,0) :
=LAMBDA(r,BYROW(r,LAMBDA(e,RANK(e,r,0))))(MAP(B2:B5, C2:C5, D2:D5, LAMBDA(a,b,c,RANK(a,B2:B5)*100+RANK(b,C2:C5)*10+RANK(c,D2:D5)*1)))
Let me know!
NOTE: This would work great until 9 players, if you or anyone else needs it for more, you should change 100,10,1 with the amount of players + 1 elevated to the "priority" of the category. The first one the highest. For example, for 15 players, I would multiply the first ranking by: 16^3,16^2 and 16^1. For 20 players and 4 categories: 21^4,21^3,21^2,21^1 - Hope it's clear for universalization!

I would like that a numeric list indicate movement when a value in the same row changes to another

An example of what im asking for
Im asking if there's a way to "mark" in the B column when a value changes in position respect at the C column.
Like if new data came and the EXAMPLE1 changes to the C8 cell, that the number in the B8 column show that it has a lower position.
Sheet : https://docs.google.com/spreadsheets/d/1pLYqhkLuAS8ZgjPnsZTZyU5yuPXVgm0IRUPIF2FBKkM/edit?usp=sharing
Google Sheets are better formulated in numeric value. In view with your screenshot provided, I saw player, and I assumed your player comes with various other numerical value along such as scores, age, weight, etc.
With the aid of the numerical value, you can formulate a deductive relation by finding who is best ranked number 1.
Here's an example:
As you can see from the picture above, assumed the greater the age, the higher the rank, you may use countif to count the other bigger value, while you can combine use count for deduction, and that builds the sequence from getting number 1 the older, and last the younger
Hope you find it helpful

Count string occurrence IF 2 conditions are met

I have this data set (example)
It shows different responses for different towns and what industries the respondent thinks has job openings (e.g Akron has 2 rows (2 respondents), with different industries given)
Now I want to chart/gather from that data set, the count of each industry for each town: So using this table setup, I want a formula that shows, for example, how many times "restaurant" was listed for Akron...
So here's what I want a formula to give me, in cell B63, ("Akron" row, "restaurant" column) for ex. This is paraphrasing in plain English what I want it to do. I have tried countless variations of COUNTIFS, IFS, MATCH, SUM, INDIRECT, LOOKUPS... etc and have not been able to get the numbers that reflect the data given.
=count if ("restaurant" appears in the range B53:D60 AND if those occurrences are in rows starting with "Akron" (in the range A53:A60))
The main hang-up, obviously is that these 2 different criteria encompass 2 different sized ranges (not something countifs like...) So how can I get around that barrier?
A final note: the imgs/ex given are small representations of a much larger range that I'm actually working on... so yes, I could make a nifty formula for each town that has just the town rows as my range...(COUNTIF likes this approach!) but I've got many more towns of various row counts... it takes too long to make a town specific range or diff formula for each town... I prefer 1 formula that looks through all the town rows/range and all the "Industries" range...
=COUNTIF(FILTER(DATA_RANGE,TOWN_NAME="TARGET_TOWN_NAME"),"=TARGET_INDUSTRY")
Example use
=COUNTIF(FILTER(A2:C,A2:A="A"),"=1")
Counts the responses of 1 under town A.
Example Screengrab

using sum and countifs to get a percentage of 'yes'es across multiple columns by month and team - is there a simpler way?

I've been asked to create a summary for some google form responses, and though I have a working solution, I can't help but feel there must be a more elegant one.
The form collects data related to case checking - every month each team (there's 100+ teams) has to check a certain number of cases based on how many staff are in their team, and enter the results for each case they've checked in the google form. The team that have set this up want me to summarise the data by team, month, and section of the form (preliminary questions, case recording, outcomes, etc). There are 8 sections on the live form, ranging from 1-13 questions, all with Yes/No/NA/blank answers.
(honestly, it's not how I'd have approached setting all this up, but that is out of my hands!)
So they're essentially looking for a live monthly summary with team names down the side, section names along the top, and a %age completed that will keep up with entries as they come in (where we can also use importrange and query to pull the relevant bits into other google sheet summaries, as and when needed).
What I've currently got is this:
=iferror(sum(countifs('Form Responses'!$B:$B,$A3,'Form
Responses'!$F:$F,"Yes",'Form Responses'!$E:$E,">="&$B$1,'Form
Responses'!$E:$E,"<"&edate($B$1,1)),countifs('Form
Responses'!$B:$B,$A3,'Form Responses'!$G:$G,"Yes",'Form
Responses'!$E:$E,">="&$B$1,'Form
Responses'!$E:$E,"<"&edate($B$1,1)),countifs('Form
Responses'!$B:$B,$A3,'Form Responses'!$H:$H,"Yes",'Form
Responses'!$E:$E,">="&$B$1,'Form
Responses'!$E:$E,"<"&edate($B$1,1)),countifs('Form
Responses'!$B:$B,$A3,'Form Responses'!$I:$I,"Yes",'Form
Responses'!$E:$E,">="&$B$1,'Form
Responses'!$E:$E,"<"&edate($B$1,1)),countifs('Form
Responses'!$B:$B,$A3,'Form Responses'!$J:$J,"Yes",'Form
Responses'!$E:$E,">="&$B$1,'Form
Responses'!$E:$E,"<"&edate($B$1,1)),countifs('Form
Responses'!$B:$B,$A3,'Form Responses'!$K:$K,"Yes",'Form
Responses'!$E:$E,">="&$B$1,'Form
Responses'!$E:$E,"<"&edate($B$1,1)))/(countifs('Form
Responses'!$B:$B,$A3,'Form Responses'!$E:$E,">="&$B$1,'Form
Responses'!$E:$E,"<"&edate($B$1,1))*6),0)
It works, but it feels like a bit of a brute-force-and-ignorance solution. I've tried countifs & array, I've looked a pivot but I can't get the section groups, I've had a play with query but I can't figure out how to ask it to count all Yeses in multiple columns at once.
Is there a more elegant solution, or do I have to resign myself to setting up the next financial year's summaries like this?
Edit:
You can use plain array boolean multiplication to achieve the count, as trues are converted to 1s and false are converted to 0s:
=TO_PERCENT(ARRAYFORMULA(
SUM((f!F1:K="Yes")*(f!E1:E>=B1)*(f!E1:E<EDATE(B1,1))*(f!B:B=A3))/
SUM(6*(f!E1:E>=B1)*(f!E1:E<EDATE(B1,1))*(f!B:B=A3))
)
)
Renamed Form Responses to f
Numerator: SUM of
Question filter (f!F:K =Yes) and
Month filter (f!E:E is within month of B1) and
Team filter(B:B = A3)
Denominator: 6 times the SUM of
Month filter (f!E:E is within month of B1) and
Team filter(B:B = A3)
On this sample sheet that you provided you'll notice two new tabs. MK.Retab and MK.Summary.
On MK.Retab is a single formula in A2 that "re-tabulates" all of your survey data into a format that is much easier to analyze going forward. That tab can be "hidden" on your real project. It will continue to build the 6 column dataset forever. It would be a sort of "back end" sheet, only used to supply data to any further downstream analysis.
On MK.Summary is a single formula in cell A1 that Query's that dataset from MK.Retab and shows the percentage of Yes's by month by section by team in a format similar to what you proposed. I coded it to display the most recent month at the left, immediately to the right of the team names, and to push historical data off to the right. Even though people are often used to seeing time go from left to right, I find that the opposite method nice because it keeps you from having to scroll sideways to see the most recent data. It is very simple to change should you want to by getting rid of the "desc" that you find in the "order by" clause of the query string.
I find this kind of two step solution to problems like your useful, because while the summary migth not be exactly what you want, it's always easier to build formulas and analyses off of the data as laid out in the MK.Retab sheet.
As for the formula in MK.Retab, it is based on a method that I came up with a while back that constructs a large vlookup where the [search key] is actually a sequence of decimal numbers that is built by counting the number of rows in your real data set and multiplying by the number of columns of data that need to be repeated for each row. I built a demo some time ago that I'm happy to share with folks if you want to understand better how it works.
You said that your goal was to understand the formulas so that you could modify them going forward as needed. I'm not sure how easy that will be to do, but I can try my best to answer any questions you might have about the method or the solution generally.
What I can tell you is that some of the formulas are more complicated than they need to be because you just used Q1 Q2 Q3 etc instead of the actual questions. if you had a list of the questions asked somewhere (on some other tab, say), and what you wanted to call/name their corresponding "sections", it would make the formula significantly less complicated. As it stands, I had to use the appearance of the word "Comments", in row 1 to distinguish between where one section ended and another section began. The upside to that decision though, is that the formula I wrote is infinitely expandable to the right. That is, if you were to add another 100 columns worth of questions and answers to the sample set here, the formula would be able to handle that and break it out, so long as there was the word "Comments" between each section.
Hope all this helps.

How to Sum lots of IF results, where SUMIF and SUMIFS cannot be used

Have a sheet with items which have data attributes, and may be used for multiple purposes.
There is a lookup table to lookup a score, based on the attributes.
So I can get the score for each item, see the top right section, and then sum that for each of the purposes. So purpose 1 has 11 data attribute points etc.
The score formula is included in the image for reference.
However, rather than copy all the data and score it, ideally would like a formula that can just go into a scoring column. Otherwise, with say 200 items, I need to have 201 columns just to score this one thing...
However, sumifs and sumif won't do this. What I really want is a "sum(foreach cell in range, do this formula)"
Does anyone know how this might be done?
Just on this mini example, you could use
=ArrayFormula(sum(if(C4:E4="yes",vlookup(C$2:E$2,$B$9:$D$11,match(C$3:E$3,$C$8:$D$8,0)+1,false))))
so you do a lookup on attribute 2 to find which column to do the lookup on attribute 1.

Resources