I have produced a set of data using a countif as exampled below:
=COUNTIFS(Matrix!$C6:$EZ6,"1",Matrix!$C$5:$EZ$5,"Attainment",Matrix!$C$3:$EZ$3,AD$3)
What this is doing is looking at a students grades against a subject and calculating the count of that grade. I have 5 grades, *, 1, 2, 3, 4, so I have 5 sets of calculated columns for each subject. What I am now trying to do is a weighted sum using the results of these countif's. * = 0, 1=1,2=2 etc, however students can get more than 1 grade per subject so I need to average these.
Student X got two 2 grades for biology and one 3 grade, I need to do (2x2/2) + (1x3/3) = 2.3
I have tried
=SUM((F4*0)+(AG4*1/AG4)+(BH4*2/BH4)+(CI4*3/CI4)+(DJ4*4/DJ4))
However, I get a divide by zero error as not all cells hold a value above zero.
Is there a way to create a formula that says if the cell value is greater than zero then do the calculations, but if not ignore. I can't do a nested if. So, if the sum of AG4*1/AG4 results in a number then add this, but if it produces a zero, do not and move on and do the same for the next calculation. I can't do a nested if as more than one calculation may return a positive value.
Your weighting formula seems wrong. You wrote '(2x2/2) + (1x3/3) = 2.3'. However, (2x2/2) + (1x3/3) returns 3.
Shouldn't it be (2x2) + (1x3) / (2+1) = 2.3 ?
Try using the following formula:
=(F4*0)+(AG4*1)+(BH4*2)+(CI4*3)+(DJ4*4) / SUM(F4,AG4,BH4,CI4,DJ4)
You can use wrap it in an IFERROR function to avoid errors for students with no grades
Related
I would like to know how does Excel think to calculate the values on the function PERCENTILE.INC. I'm making some studies on Percentile and Quartile, I got the below results:
How does Excel think to calculate the values on column F?
Here's the formulas I'm using:
=PERCENTILE.INC(B2:B21; 0,75) ==> F2
=PERCENTILE.INC(B2:B21; 0,50) ==> F3
=PERCENTILE.INC(B2:B21; 0,25) ==> F4
=PERCENTILE.INC(B2:B21; 0,00) ==> F5
Short answer - the position of a given percentile when the data is sorted in ascending order, using percentile.inc, is given by
(N-1)p+1
where p is the required percentile as a fraction from 0 to 1 and N is the number of points.
If this expression gives a whole number, you take the value at this position (e.g. percentile zero gives 1, so its value is exactly 22). If it's not a whole number, you interpolate between the value at the position given by the whole number part (e.g. for p=0.25 it's 5 and the value at this position is 52) and the value at the position one higher (in this case position 6 so the number is 55), then multiply the difference of the two values (3) by the fraction part (0.75) giving you 2.25 and finally add this to the lower of the two values giving you 54.25. A shorter way of saying this is that you go a quarter of the way between the two nearest values. So you have:
If you wished to show the logic as an Excel formula, you could implement the expression shown here on the right (where h, in the second column of the table, is the position calculated from the formula above and x is the value at that position)
like this:
=LET(p,J3,
range,I$2:I$21,
N,COUNT(range),
position,(N-1)*p+1,
lower,FLOOR(position,1),
fraction,MOD(position,1),
upper,CEILING(position,1),
lowerValue,INDEX(range,lower),
upperValue,INDEX(range,upper),
difference,upperValue-lowerValue,
lowerValue+fraction*difference)
I need to create a running product from a column of numbers (I could use a row, but a column is easier to demonstrate here.) The input might be any arbitrary array. In fact, in the application where I would deploy this, it will not be a range, but rather another dynamic array within a LAMBDA formula. Here is an example of the Input column of numbers and the desired Output from the formula:
Inputs
Expected Dynamic Array Output
10
10
8
80
3
240
4
960
5
4800
The formula would spill the results.
There are lots of solutions for a running total, but I've found no solution for a running product. I have tried a few different approaches, including SUBTOTAL and AGGREGATE with no success. I have also built a number of approaches that get the result, but are hard-coded to a fixed number of rows. I need the formula to adapt to any arbitrarily sized number of rows. The following formula is the closest I have gotten so far.
This LET formula delivers the result, but, as you can see is fixed to 5 rows:
=LET( a, {10;8;3;4;5},
v, SEQUENCE( ROWS(a) ), h, TRANSPOSE( v ),
stagr, (v - h + 1) * (v >= h),
m, IFERROR(INDEX( a, IF(stagr>0,stagr,-1), ), 1),
almost, INDEX(m,v,h) * INDEX(m,v,h+1) * INDEX(m,v,h+2) * INDEX(m,v,h+3) * INDEX(m,v,h+4),
result, INDEX( almost, , 1 ),
result )
The arbitrary array of numbers input is placed in the variable a.
The next step is to create some indexes that will be used to address these numbers: v is a sequence of vertical rows for each number in a and h is a the same sequence, but transposed into columns. stagr is an index matrix that is created from v and h that will later be used to address each item in a to form it into a multiplication matrix. If you replace the last result with stagr, you can see the shape of stagr. It just shifts a column down by one row until they are shifted all the way down.
Now we create the mulitplication matrix m using stagr by simply using INDEX, like this: INDEX(a,stagr). But this is not exactly what is needed because it takes the first row value (10) and replicates it because an INDEX of 0 is treated the same as 1. To get what we want, I forced an error by using and internal IF statement like this: INDEX( a, IF(stagr>0,stagr,-1) ) to replace the 0 results with -1. i.e. it will produce this:
Now, replace the errors with 1's by using IFERROR, so this explains how m is created and why. The result is a matrix like this:
and by multiplying m row-wise, we get the output we want, but this is where I fail.
For illustration, I created a variable almost that shows how I am trying to do a row-wise multiplication.
almost, INDEX(m,v,h) * INDEX(m,v,h+1) * INDEX(m,v,h+2) * INDEX(m,v,h+3) * INDEX(m,v,h+4)
You can see that I crudely multiplied one column times the next and the next... and using h + offset to get there. This produces the almost matrix and result just delivers the first column of that matrix, which contains the answer.
While an answer might be a good replacement for almost that would be dynamically sized, that is not my real question. I want a running product and I suspect that there is a wholly different approach than simply replacing my almost.
Just to be clear, the result must be a dynamic array that spills with no helper cells or CSE drag-down.
oh... and no VBA. (#stackoverflow - please add a no-VBA tag)
The only way I can find is to use DPRODUCT with OFFSET, but that requires a title row. It does not matter what is in the title row(it can even be empty), just that it is included.
=DPRODUCT(OFFSET(A1,0,0,SEQUENCE(COUNT(A:A),,2)),1,$ZZ1:$ZZ2)
The $ZZ1:$ZZ2 can be any empty cell reference.
If the values in A are dynamic then we can do:
=DPRODUCT(OFFSET(A1,0,0,SEQUENCE(ROWS(A2#),,2)),1,$ZZ:$ZZ)
There are plenty of interesting answers here. But, if summation is easy why not take logarithms of the number you want to multiply, sum those logarithms and then calculate the exponent of your sum to return to the product of the original numbers.
i.e. exploit the fact that ln(a * b) = ln(a) + ln(b)
Whilst not available to everybody (yet) we can use SCAN()
Formula in A1:
=SCAN(1,{10,8,3,4,5},LAMBDA(a,b,a*b))
The 1st parameter is our starting value, meaning the 1st calculation in the nested LAMBDA() is '1*10'.
The 2nd parameter can both take a 1D- & 2D-array (written or range-reference).
The 3rd parameter is a nested LAMBDA() where the result of our recursive function will then be used for the 2nd calculation; '10*8'. And the 3rd...etc. etc.
In the above sample a vertical array is spilled but when horizontal input is used this will obviously result in an horizontal spilled output. When a 2D-array is used this will spill a 2D-array as result.
The formula I would like to use looks something like this: SUMPRODUCT(x^(1:n),y^(n:1)). n=values in column A. 1:n is the exponents in forward progression from 1 to n in steps of 1. n:1 is the exponents in reverse progression from n to 1 in steps of 1. I would like the formula to be dynamic to fill in column B with the n values based on column A.
Try:
=SUMPRODUCT(5^ROW(1:100))
Or in Excel O365
=SUM(5^ROW(1:100))
As per #RonRosenfeld, a more sturdy solution could be =SUM(5^SEQUENCE(100)) in Excel 365.
EDIT: Based on OP's comments he could use (no O365):
=SUMPRODUCT(5^ROW(A1:INDEX(A:A,COUNTA(A:A))),7^LARGE(ROW(A1:INDEX(A:A,COUNTA(A:A))),ROW(A1:INDEX(A:A,COUNTA(A:A)))))
You can store the powers in a column and use the array formula:
SUM((A1:A100)^$B$1) where A column contains 5 in each cell and B column contains the range of powers you want to use. You can use an array formula in the different cell to get the answer.
Use the SERIESSUM function
The Excel SERIESSUM function returns the sum of a power series, based on the following power series expansion:
Power Series Equation
The syntax of the function is:
SERIESSUM( x, n, m, coefficients )
Where the function arguments are:
x - The input value to the power series.
n - The first power to which x is to be raised.
m - The step size that n is increased by, on each successive power of x.
coefficients - An array of coefficients that multiply each successive power of x.
The number of values in the supplied coefficients array defines the number of terms in the power series. This is illustrated in the following examples.
Example 1:
In the spreadsheet below, the Excel Seriessum function is used to calculate the power series:
5^1 + 5^2 + 5^3 + 5^4 + 5^5
formula: =SERIESSUM( 5, 1, 1, {1,1,1,1,1} )
output = 3905
Example 2:
1 * 2^1 + 2 * 2^3 + 3 * 2^5 + 4 * 2^7 + 5 * 2^9
formula: =SERIESSUM( 2, 1, 2, {1,2,3,4,5} )
output = 3186
I hope this is of help.
An Alternative Answer again. I think the correct for your case :-)
Using the SERIESSUM function allows the use of different coefficients therefore the reason for the use of the coefficients in an array. But because the coefficients are the same then this is simply a geometric progression.
The following formula will do that for you:
=n+n*(n)^(1)*(1-(n)^c)/(1-n)
where "n" is the number (5) and "c" is the number of the series (100)
This becomes:
=5+5*(5)^(1)*(1-(5)^100)/(1-5)
=SUMPRODUCT(5^ROW(A1:INDEX(A:A,COUNTA(A:A))),7^LARGE(ROW(A1:INDEX(A:A,COUNTA(A:A))),ROW(A1:INDEX(A:A,COUNTA(A:A)))))
This formula worked flawlessly!!!
Thank you #JvdV and everyone else for your efforts in helping me! GREATLY APPRECIATED!
In trying to systematically enumerate the possibilities when rolling four identical but loaded four-sided dice, I came across some unusual excel behavior. Hoping someone can shed some light on what's going on under the hood.
The following table illustrates the possible rolls of a die:
1000 A
0100 B
0010 C
0001 D
each row is a possibility with a distinct probability. In excel, this information can be made to occupy a 4x4 cell area--that is, the letter labels above are merely for convenience.
In trying to display all possible combinations of four rolls of such a die-- where the fist combination might be A + A + A + A or 4000, the second might be B + A + A + A or 3100, and so on for each of the 4^4=256 possibilities--I decided that I wanted to systematically offset A by 0,1,2, or 3 rows for each of four rolls then sum the results. In other words, each possible group of 4 roles can be thought of as 4 copies of row A, each of which offset by some number of rows between 0 and 3, for example {0;0;0;0} or {1;0;0;0} in the first and second case enumerated directly above.
Oddly, though, I get the following. (all formulas are array formulas keyed in with shift+ctrl+enter).
=TRANSPOSE( SUM( OFFSET( A, 4x1ArrayOfRowOffsets, 0)))
displays the correct sum when entered into a 1x4 range. Likewise if =TRANSPOSE(...) is replaced by =INDEX(...,1,1). I take it because both functions natively support array arguments. However,
=SUM( OFFSET( A, 4x1ArrayOfRowOffsets, 0))
does not work--it seems that here the summation is conducted along the 4 rows returned by offset, each of which has value 1--it incorrectly displays only the value 1, even when evaluated in a multicell range as an array formula. Oddly,
=SUM( TRANSPOSE( OFFSET( A, 4x1ArrayOfRowOffsets, 0)))
does not work either--the transpose makes it so the summation is properly conducted along the columns returned by offset, but seems to throw out all but the first column.
Please note that, although the problem statement does not involve VBA, the lack of transparent array formula auditing in Excel proper (intermediate steps return #VALUE errors even when the final answer computes) likely means that, in order to investigate this problem, someone will have to write a bit of VBA that calls worksheet functions and manually outputs the intermediate calculations. This is why I posed a version of this question, here.
Interweaving INDEX calls anywhere but the outside/first function call does not fix the problem.
To try and see what is going on, I investigated further.
=INDEX( OFFSET( A, {w;x;y;z}, 0), 1, {1,2,3,4})
correctly displays the four rolls when entered into a 4x4 range. As before w, x, y, and z are integers between 0 and 3 indicating row offsets from "A" in the table, above. Furthermore,
=COLUMNS( OFFSET( A, {w;x;y;z}, 0))
returns the following when entered into a 5x5 range:
4 4 4 4 4
4 4 4 4 4
4 4 4 4 4
4 4 4 4 4
n/a n/a n/a n/a
All that is to say, calling SUM(OFFSET(---)) with array arguments seems to produce varied output depending on what is doing the calling--specifically, whether or not the caller is a function which natively accepts proper array arguments. Why is this? What is actually going on, here?
I've structured a formula that should spit out a numerical answer that is basically a simple sum formula with IF statements assigning numerical values to qualitative inputs. Apologies for the length, I am looking at a number of different factors.Formula is:
Cell F36 contains:
=IF(F32="Medium-High", 18, IF(F32="High", 24, SUM(F16, IF(F20="High",5,IF(F20="Medium-High",4,IF(F20="Medium",3,IF(F20="Low-medium",2,IF(F20="Low",1))))),IF(F24="High",5,IF(F24="Medium-High",4,IF(F24="Medium",3,IF(F24="Low-Medium",2,IF(F24="Low",1))))),IF(F28="High",5,IF(F28="Medium-High",4,IF(F28="Medium",3,IF(F28="Low-Medium",2,IF(F28="Low",1,IF(F28="N/A",0)))))),IF(F30="N/A",0,IF(F30="High",5,IF(F30="Medium-High",4,IF(F30="Medium",3,IF(F30="Low-Medium",2,IF(F30="Low",1)))))),IF(F32="High",5,IF(F32="Medium-High",4,IF(F32="Medium",3,IF(F32="Low-Medium",2,IF(F32="Low",1,IF(F32="N/A",0)))))))))
F16 - contains values from 1 to 5
F20, F24, F28, F30, F32 - Are dropdowns, where you choose a value: Low, Low-Medium, Medium, Medium-High, High;
Right now, based on a test input, where: F16 = 5, F20 = Low (1), F24= Medium-High (4), F28 = N/A (0), F30 = Medium (3), F32 = Medium (3) my output in F36 is 11, however doing simple adding, I should be at 5+1+4+0+3+3 = 16.
Where am I losing 5 points?
You can create a table allocating numerical output to each qualitative inputs and using vlookup to get your output. For example, for a table created on K19:L25, the following can be used:
=SUM(F16,VLOOKUP(F20,K19:L25,2,FALSE),VLOOKUP(F24,K19:L25,2,FALSE),VLOOKUP(F28,K19:L25,2,FALSE),VLOOKUP(F30,K19:L25,2,FALSE),VLOOKUP(F32,K19:L25,2,FALSE))
EDIT:
Tried your formula and it gives the correct result. Maybe your 5 in F16 is not a numerical value? You can test it by using
=ISNUMBER(F16)
and it should give a TRUE if it is a number.
Debug embedded IFs is just hell.
What you are doing is recode a 5 levels scale. You may use alternative solutions.
a. place the 5 text values (from "Low" to "High") somewhere in a sheet, say in T1:T5, even better, give this range a name
then you can retrieve the values you search with
MATCH(F20,$T$1:$T$5,0)
b. if it's suitable for your use, you may use combo boxes, presenting the 5 choices and giving the desired answer (from 1 to 5) in a linked cell.
(maybe not the answer, but I can't comment…)
(This should be a comment but I needed the formatting capabilities of an answer)
This is the current logic of your formula:
Check cell F32: "Medium-High" outputs 18, "High" outputs 24
If F32 is neither of those, then SUM the following:
F16
Lookup for F20, F24, F28, F30, and F32 where the lookup for each is:
"High" = 5
"Medium-High" = 4
"Medium" = 3
"Low-Medium" = 2
"Low" = 1
I find it strange that you first check cell F32 only to check it again later in the sum. Because this current logic produces incorrect results, we can't really advise how to fix it without sample data and expected results. My guess is you are summing too many lookups by including the F32 in there, but that's just speculation without data.