I'm trying to use the aggregate function to take the average of the reciprocals of an array of values. This works fine for averaging the given values but doesn't seem to be working on their reciprocals. Below is the function I'm using:
Works fine: =AGGREGATE(1, 6, AA11:AA16)
Not working: =AGGREGATE(1, 6, 1/(AA11:AA16))
Does anyone know the source of the error and whether or not there's a work-around?
Clarification
I cannot use array formulas because they contribute too much to the file size.
You could instead find the average of the reciprocals using an array formula, for example:
={AVERAGE(1 / AA11:AA16)}
(CTRL + SHIFT + ENTER to enter the array formula)
To ignore error values to fully replicate the aggregate function you have used you could add an IF into the array formula:
=AVERAGE(IF(ISERROR(AA11:AA16), "", 1 / AA11:AA16))
Alternative option...
=SUMPRODUCT(1/AA11:AA16)/COUNT(AA11:AA16)
Related
In the formula below, a #Value! error is returned.
=FILTER(FIND(";"&AS4756:AS4762&{6,7},AG4756),ISNUMBER(FIND(";"&AS4756:AS4762&{6,7},AG4756)))
Where ag4756 is 8034000;Y8033343543543;Y;38918;BS7 9XL;9;Male;N;N;N
and AS4756:AS4762 is
BS
NP
SN
GL
BA
CF
TA
When I chose evaluate formula, it returns the number 31 for the string BS7, and errors for all others. I'm trying to filter out the errors from the result, so I only get the result which is not an error. It also correctly returns TRUE for BS7, and false for all the others. But then the next step results in the error. Can anyone help?
edit: I want to return the position of the substring that starts with BS7. Or BS6, or NP6, or NP7, and so on.
Alright, I hope the following helps you out a bit; let's assume data (vertical) {BS;NP;SN;GL;BA;CF;TA} to be in A1:A7 and the lookup-string to be in B1. You are then concatenating a 2nd (horizontal) array {6,7} which would make up the following matrix:
Now to find these values in B1 using FIND(";"&A1:A7&{6,7},C1) would result in:
The next step for you would be to gather the numeric value. However, for the 2nd parameter, you have provided a 7*2 matrix and not a 1D-vertical or horizontal array of values. Therefor FILTER() will error out on exactly that step, returning the '#VALUE!'! And even so, if you would try to use MMULT() tricks to retrieve this array correctly you'd still need to deal with the fact you are trying to filter a matrix from the 1st parameter that is filled with errors. Therefor, I've shown how you could get the position from a relative easy formula that would deal with errors too:
=MAX(IFERROR(FIND(";"&A1:A7&{6,7},B1),""))
And to get the correct substring, use:
=MID(B1,MAX(IFERROR(FIND(";"&A1:A7&{6,7},B1)+1,"")),3)
Now that leaves us with the probability you have more potential substrings you'd like to be returned. If that is the case, let me know in the comments.
I've got the following formula that works correctly
=SUM(COUNTIFS(MachineData!N:N,{"*Arlington*","*RenewNorfolk*"}, MachineData!$X:$X,"Y"))
but now if I try to do the same but with "not arlington or not renewnorforlk" I get the wrong answer (it counts double the amount of values that I want to count)
=SUM(COUNTIFS(MachineData!N:N,{"<>*Arlington*","<>*RenewNorfolk*"}, MachineData!$X:$X,"Y"))
what is happening here?
Your first statement is equivalent to
=COUNTIFS(MachineData!N:N,"*Arlington*", MachineData!$X:$X,"Y") + COUNTIFS(MachineData!N:N,"*RenewNorfolk*", MachineData!$X:$X,"Y")
where the array constant is manually split into it two constituent parts.
If you try this with the second statement
=COUNTIFS(MachineData!N:N,"<>*Arlington*", MachineData!$X:$X,"Y") + COUNTIFS(MachineData!N:N,"<>*RenewNorfolk*", MachineData!$X:$X,"Y")
we can see that anything that isn't either Arlington or RenewNorfolk gets counted by both COUNTIFS statements, which isn't what we want the result to be.
The simplest solution is to use
=COUNTIFS(MachineData!N:N,"<>*Arlington*", MachineData!N:N,"<>*RenewNorfolk*", MachineData!$X:$X,"Y")
which requires all the criteria to be met for a data item to be counted.
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.
Many thanks for taking the time to read this.
I've got a function to return the closest value that is less than a given value:
=MAX(IF(O80:O85<Y80,O80:O85))
This works well and I now want to multiply it by the value on the right of the value that was found so I am trying to use the offset function:
=MAX(IF(O80:O85<Y80,O80:O85))*(1+OFFSET(MAX(IF(O80:O85<Y80,O80:O85)),0,1))
But this isn't working. I've done a similar thing with another function and the offset works perfectly Does anybody know why it's not the case here?
I am using Ctrl + Shift + Enter
Many thanks
The offset function first needs a reference, but the max function just gives a value.
This would be a solution based on your first function
=(MAX(if(O80:O85<Y80,O80:O85)),O80:O85,0))* (1+INDEX(P80:P85,MATCH(MAX(if(O80:O85<Y80,O80:O85)),O80:O85,0)))
ARRAY Formula: CTRL + SHIFT + ENTER
IMO, the best pseudo-MAXIFS if you don't have Office 365 with the new MAXIFS is AGGREGATE as a standard non-array formula.
=aggregate(14, 7, O80:O85/(O80:O85<Y80), 1)
Multiply that result against the matching value in P80:P85.
=aggregate(14, 7, O80:O85/(O80:O85<Y80), 1)*index(P80:P85, match(aggregate(14, 7, O80:O85/(O80:O85<Y80), 1), O80:O85, 0))
You can use INDEX-MATCH to make easily what you need:
=INDEX(where-is-your-data,MATCH(what-is-the-target,where-is-your-data,Less-than-option))
In your case:
=INDEX(O80:O85,MATCH(Y80,O80:O85,1))
It's important to class your data in ascending order because the formula will give the closest value by checking your data one after one and stop without checking further the closest.
For the second part, if you need to multiply by an offset to the value on the right of the selected value, just make this:
=INDEX(O80:O85,MATCH(Y80,O80:O85,1))*OFFSET(INDEX(O80:O85,MATCH(Y80,O80:O85,1)),0,1)
If have the following function that is used to calculate SMALL:
=IFERROR(AGGREGATE(15; 6; Table5[Salary]/(Table5[Letter]="F") /(Table5[Level]=B2) /(Table5[[Title ]]=A2); 1); "-")
Which works perfectly fine when the first parameter is 15 (SMALL) or 14 (Large). But if I try to calculate the median ( replacing 15 with 12 ) the error value "-" is returned. Any ideas?
The median does not accept an array entry, it must be 14 or higher in the AGGREGATE to accept array entry.
You will need to use MEDIAN(IF()) as an array formula:
=IFERROR(MEDIAN(IF((Table5[Letter]="F")*(Table5[Level]=B2)*(Table5[[Title ]]=A2);Table5[Salary]));"-")
Being an array formula it needs to be confirmed with Ctrl-
Shift-Enter instead of Enter when exiting edit mode. If done correctly Excel will put {} around the formula.