I'm trying to make a scoresheet for a competition and I faced a problem when it comes to ranking the competitors.
An example can be found here: https://docs.google.com/spreadsheets/d/1tSiHxGlgNo9oYMypXJ9_ZGrn8O_POQkHspLXhVL9k7M/edit?usp=sharing
The competitors should be ranked by these rules:
Best attempt (higher wins), if this is a tie, then by
Bodyweight (higher wins), if this is also a tie, then by
Second best attempt (higher wins), if this is also a tie, then by
Third best attempt (higher wins), if this is also a tie, then they share a rank
If there no valid attempts (0 in the cell), no rank shall be given
I've been able to get to the 2nd rule (where it compares the bodyweights in case the best attempts are same) but beyond that I'm out of knowledge.
This is what I currently have in cell F2:
=IF(B2=0;"";RANK.EQ($B2; $B$2:$B$10) + COUNTIFS($B$2:$B$10; $B2; $C$2:$C$10; ">" &$C2))
Use weights that differ by order of magnitude with each column, like this:
=arrayformula(
iferror(
rank(
B2:B * 1000000 + C2:C * 10000 + D2:D * 100 + E2:E;
B2:B * 1000000 + C2:C * 10000 + D2:D * 100 + E2:E
)
/
sign(B2:B + D2:D + E2:E)
)
)
This array formula should go to row 2 of a free column. It will fill the whole column in one go.
Related
I am trying to weighted average of available stock ie 888 Items. We operate FIFO so that means I need to start sum from recent date backwards. How do i only select those cells that sum up to available stock balance (888) then sumproduct with the price?
Date Items Recieved Price
9/1/2022 254 $25.00
8/25/2022 242 $25.00
8/18/2022 230 $65.00
8/11/2022 218 $77.00
8/4/2022 206 $45.00
7/28/2022 194 $77.00
7/21/2022 182 $89.00
7/14/2022 737 $74.00
7/7/2022 1292 $86.00
6/30/2022 1847 $87.00
Query, Arrayformula & SUMproduct
You tagged both Excel and Google sheets. They're different. In Excel (Office 365) you can do this using:
=LET(stock,888,
data,B2:C11,
items,INDEX(data,,1),
price,INDEX(data,,2),
cumulative,SCAN(0,items,LAMBDA(a,b,a+b)),
r,XMATCH(stock,cumulative,1),
correction,INDEX(items,r)+stock-INDEX(cumulative,r),
SUMPRODUCT(
IFERROR(
VSTACK(
TAKE(items,r-1),
correction),
correction),
TAKE(price,r)))
stock is the number to sum up to.
data is the range containing both the items and prices.
SCAN is used to get the cumulative sum of all items row-by-row.
XMATCH is used to find the row (r) in the cumulative sum where the value is greater than or equal to the stock value.
r is used to correct the items in that row to the value required to get the cumulative sum up to row r equal to the stock value. (Item in row r + stock - cumulative sum in row r).
I than take the rows before r of the items and add (stack) the correction items value calculated and use that in a SUMPRODUCT with the prices up to r.
If r is the first row it'll throw an error at the TAKE(items,r-1)-part, if so IFERROR makes sure the corrected value is used without stacking it on previous items values.
Edit: since you mentioned FIFO you'd probably be interested to calculate from the bottom up. In this case you could use:
=LET(stock,888,
data,SORT(A2:C11,1,1),
items,INDEX(data,,2),
price,INDEX(data,,3),
cumulative,SCAN(0,items,LAMBDA(a,b,a+b)),
r,XMATCH(stock,cumulative,1),
correction,INDEX(items,r)+stock-INDEX(cumulative,r),
SUMPRODUCT(
IFERROR(
VSTACK(
TAKE(items,r-1),
correction),
correction),
TAKE(price,r)))
It works the same, it just uses an extra column for the data, so it could sort from old (first in) to new.
And it's unclear if you wanted this SUMPRODUCT or the average of it, but that's simply adding /stock to the last argument of LET
Let's say in A1 I have the number 500 and in A45 I have the number 323.
How do fill cells A2->A44 with numbers that evenly reduce down to the end number of 323 (A45)?
go to File
select Spreadsheet settings
choose Calculation
and turn on Iterative calculation
then use this formula:
=ARRAYFORMULA(INDIRECT("A"&
MAX(IF(A3:A<>"", ROW(A3:A), )))+SORT(ROW(INDIRECT("A1:A"&
MAX(IF(A3:A<>"", ROW(A3:A), ))-2)), 1, 0)*(A1-INDIRECT("A"&
MAX(IF(A3:A<>"", ROW(A3:A), ))))/(
MAX(IF(A3:A<>"", ROW(A3:A), ))-1))
To get the step, find the difference between A1 and A45 and divide that by the number of rows between the two cells plus 1.
Then multiply the step by the sequence 1, 2, 3... N where N is the number of rows between the two cells, and subtract the product from A1, like this:
=arrayformula( A1 - sequence(rows(A2:A44)) * ((A1 - A45) / (rows(A2:A44) + 1) ) )
To get integers that will at various steps be one larger or smaller than others, add round(), like this:
=arrayformula( round( A1 - sequence(rows(A2:A44)) * ((A1 - A45) / (rows(A2:A44) + 1) ) ) )
I have some data in the following way
Category
[Range 1_min]
[Range 1_max]
[Range 2_min]
[Range 2_max]
...
A
120
130
...
B
100
119
131
140
...
I want to be able to quickly query a number and have it return the category it belongs to, for example 135 belongs to B and 121 belongs to A.
I already have a script that does this, but since there are 1000+ categories, it takes a long time to run. Is there a faster way of doing this?
Thanks.
You can use LOOKUP:
=ArrayFormula(LOOKUP(2,1/((G2>=B2:B)*(G2<=C2:C)+(G2>=D2:D)*(G2<=E2:E)),A2:A))
Addition:
For more ranges you can add MMULT (not sure it's easier):
=ArrayFormula(LOOKUP(1,5/(MMULT(--(K2>={B2:B,D2:D,F2:F,H2:H}),ROW(A1:A4)^0)*MMULT(--(K2<={C2:C,E2:E,G2:G,I2:I}),ROW(A1:A4)^0)),A2:A))
some conditions:
change first argument of LOOKUP to 1
for second LOOKUP argument change denominator to 5 (number of cols to compare + 1)
for second MMULT argument ROW(A1:A4) use row count according column count to compare (i.e. for 4 cols ->ROW(A1:A4), for 6 cols -> ROW(A1:A6) etc. )
I have a google sheet that I am using to try and calculate leveling and experience points. Column A has the level and Column B has the exp needed to reach the next level. i.e. To get to Level 3 you need 600 exp.
A B
1 200
2 400
3 600
...
99 19800
In column I2 I have an integer for an amount of exp (e.g. 2000), in column J2 I want to figure out what level someone would be at if they started from 0.
Put this in column J and ddrag down as required. Rounddown(I2,-2) rounds I2 down to the nearest 100. Index match finds a match in column B and returns the value in column A of the matched row.
=index(A2:A100,match(ROUNDDOWN(I2,-2),B2:B100,0))
Using a helper column (for example Z): put =sum(B$1:B1) in cell Z1 and drag down. This will compute the sums required for each level. In J2, use the formula
=vlookup(I2, {B:B, Z:Z}, 2) + 1
which looks up I2 in column B, and returns the nearest match that is less than or equal to the search key. It adds 1 to find the level that would be reached, because your table has this kind of an offset to you: the entry against level N is about achieving level N+1.
You may want to put 0 0 on top of the table, to correctly handle the amounts under 200. Or treat them with a separate if condition.
Using algebra
In your specific scenario, the point amount required for level N can be computed as
200*(1+2+3+...+N-1) = 200*(N-1)*N/2 = 100*(N-1/2)^2 - 25
So, given x amount of points, we can find N directly with algebra:
N = floor(sqrt((x+25)/100)+1/2)
which means that the formula
=floor(sqrt((I2 + 25) / 100) + 1/2)
will have the desired effect in cell J2, without the need for an extra column and vlookup.
However, the second approach only works for this specific point values.
I have a spreadsheet that I'm starting to use for personal money analysis.
My main sheet is called "transactions" and has headers of Category, Description, Date and Amount (it's basically a check register).
I've created a pivot report off of that sheet that contains sum, min and max of Amount by Category.
I would like to make a custom average function on that pivot report but not sure how to go about it.
What I would like to see is the average amount of negative transactions between positive ones.
My positive transactions are my paychecks and the negative transactions are any spending I do.
An example might help in what I'm trying to do here...
Let's say for category "Food" I have the following transactions (in this order)...
-20
-25
-30
100
-30
-35
-40
I'd like my average to be calculated like this...
( ( (-20 + -25 + -30) / 3 ) + ( (-30 + -35 + -40) / 3 ) ) / 2
Anyone have the slightest idea on how I can enhance my pivot report to do this?
You do it with something like:
=ARRAYFORMULA(AVERAGE(IF(Sheet1!D2:D8<0,Sheet1!D2:D8, 0)))
where column D is the amount of your example and Sheet1 contains the "transactions" of your example.
If you want to fill it for the pivot table (having the category as another criterion) you can check the answer at: https://stackoverflow.com/a/9165254/179529
=SUM(ARRAYFORMULA(((Transactions!$A2:$A)=$A2) * ((Transactions!$D2:$D)>0) * (Transactions!$D2:$D) ))
/
SUM(ARRAYFORMULA(((Transactions!$A2:$A)=$A2) * ((Transactions!$D2:$D)>0) * (1) ))
where $A2 is the cell where you have the category name in the pivot table (The $ will allow you to copy the formula to other columns in you want it per month or other second criterion.
If you want to SUM the element in column D only if they great than 0, you need to have ((Transactions!$D2:$D)>0) as the second argument and (Transactions!$D2:$D) as the 3rd argument (otherwise you will count the cells instead of SUM them).
Since AVERAGE will take blank cells as well, I've used SUM/COUNT instead. Note that COUNT is actually SUM with the 3rd argument as 1.
Also note that if you want to ignore a header line you need to define your columns with Transactions!$D2:$D, to start from the 2nd row.