I have a spreadsheet with a lot of voltage numbers and I want to get the maximum and minimum deviations from a value (the value is 0.95).
The ideal formula would be:
=MAX(IF([range of many values]<0.95,[range of many values],""))
The range is a matrix of values, if that matters.
But this doesn't work since IF doesn't like ranges.
Is there a way to do this without creating another sheet just for the IF values results?
Thanks in advance
Use the formula
=MAX([range of many values]*([range of many values]<0.95))
as an array formula, i.e. hold hold ctrl-shift when pressing enter after typing the formula.
By entering this as an array formula, the intermediate computations can return arrays. So, ]*([range of many values]<0.95) will return an array that has 1 for True, and 0 for False. This is then multiplied by the original values in the array, entry by entry, and returns an array, which will feed into the MAX function.
BTW, your original formula will also work, if it is entered as an array formula.
There are also ways you could do this with non array formulas, e.g.
=SMALL(Range,COUNTIF(Range,"<0.95"))
That works because if there are 100 values in your range and 30 are < 0.95 then the value you want is the 30th smallest value in the range
Related
I've got a massive parts spreadsheet that I'm trying to simplify. Various parts could be included in number of locations, which I would like to add up to a single list. The attached file is just an example using reindeer.
This is doable with using a bunch of SUMIF statements added together, but not practical due to the range of columns I need to include. There's gotta be a better way!?
=SUMPRODUCT(--($D$4:$J$11=$A4),$E$4:$K$11))
SUMPRODUCT can do that. Make sure the second range shifts one column, but has equal count of columns (and rows).
($D$4:$J$11=$A4) results in an array of TRUE's or FALSE's for the value in range $D$4:$J$11 being equal to the value in $A4 (no $ prior to it's row number will increase the row # referenced when dragged down).
Adding -- in front of the array converts the TRUE's and FALSE's to 1's and 0's respectively.
Multiplying that with the range to the right of it will result in 1* the value in $E$4:$K$11 for all TRUE's, which results in it's value, or 0* the value in $E$4:$K$11 for all FALSE's, which results in 0.
Summing the array of values results in the sum of all values where the condition is met in the column left from it.
SUMPRODUCT combines the multiplication of the array and summing the array results to 1 total sum.
You can use simply the SUM:
=SUM((D$4:$D$11=A4)*$E$4:$E$11,($F$4:$F$11=A4)*$G$4:$G$11, etc.)
where in etc you can put any range you want. If you don't use 2021/365 version, you must confirm the formula with CTRL+SHIFT+ENTER.
I am trying to get the max value of a column based on the Left function
What I am doing is the following :
These are the results I get when i write this into column C :
=MAX(LEFT(A:A, 2))
But what I truly want is to get in column C the max value of all column A not for each cell.
So the result should be in this case 90 for all rows.
What should be the formula here?
Just another option that gets entered normally:
=AGGREGATE(14,6,--LEFT($A$1:INDEX(A:A,MATCH("ZZZ",A:A)),2),1)
Array formulas will calculate the enitre referenced array. So care should be taken to limit the number of iterations to only the data set.
The $A$1:INDEX(A:A,MATCH("ZZZ",A:A)) part of the formula does that. It finds the last cell in column A with data in it and sets that as the upper bound. So in this instance the reference range is A1:A3. But, it will grow dynamically as data in Column A is added, so no need to change the formula each time data is added.
Update 2
Here is another solution which I think is better than my original (below)
=INT(SUMPRODUCT(MAX(SUBSTITUTE(A:A,"-",".")*1)))
it can be entered as normal (just Enter)
Orignal Answer
You need numbers and arrays
=MAX(IFERROR(LEFT(A:A,2)*1,0))
Let's break this down. Multiplying by turns your strings into numbers - since Left only returns a string
LEFT(A:A,2)*1
Unfortunately this method returns #Value if you multiply an empty string by 1. You will definitely have some empty strings in the range A:A so we wrap the whole thing with an IFERROR function.
IFERROR(LEFT(A:A,2)*1,0)
Now we still need excel to treat this as an array (i.e. a whole column of numbers, rather than just one number). So we put the MAX formula in and enter it with Ctrl+Shift+Enter rather than just Enter. The result is that the formula looks like this in the formula bar
{=MAX(IFERROR(LEFT(A:A,2)*1,0))}
which would return 90 in your example, as required
Update 1
If you are using Excel 2013 or later, you can also use the NUMBERVALUE function
=MAX(NUMBERVALUE(LEFT(A:A,2)))
again, enter it with Ctrl+Shift+Enter
I want to calculate the average over a range (B1:B12 or C1:C12 in the figure), excluding:
Cells not being numeric, including Empty strings, Blank cells with no contents, #NA, text, etc. (B1+B8:B12 or C1+C8:C12 here).
Cells for which corresponding cells in a range (A1:A12 here) have values outside an interval ([7,35] here). This would further exclude B2:B3 or C2:C3.
At this point, cells in column A may contain numbers or have no contents.
I think it is not possible to use any built-in AVERAGE-like function. Then, I tried calculating the sum, the count, and divide. I can calculate the count (F2 and F7), but not the sum (F3), when I have #N/A in the range, e.g.
How can I do this?
Notes:
Column G shows the formulas in column F.
I cannot filter and use SUBTOTAL.
B8:C8 contain Blank cells with no contents, B9:C9 contain Empty strings.
I am looking for (non-user defined) formulas, i.e., non-VBA.
From
https://stackoverflow.com/a/30242599/2103990:
Providing you are using Excel 2010 and above the AGGREGATE
function
can be optioned to ignore all errors.
=AGGREGATE(1, 6, A1:A5)
You can accomplish this by using array formulas based upon nested IFs to provide at least part of the criteria. When an IF resolves to FALSE it no longer process the TRUE portion of the statement.
The array formulas in F2:F3 are,
=SUM(IF(NOT(ISNA(B2:B13)), (A2:A13>=7)*(A2:A13<=35)*(B2:B13<>"")))
=SUM(IF(NOT(ISNA(B2:B13)), IF(B2:B13<>"", (A2:A13>=7)*(A2:A13<=35)*B2:B13)))
The array formulas in F7:F8 are,
=SUM(IF(NOT(ISNA(C2:C13)), (A2:A13>=7)*(A2:A13<=35)*(C2:C13<>"")))
=SUM(IF(NOT(ISNA(C2:C13)), IF(C2:C13<>"", (A2:A13>=7)*(A2:A13<=35)*C2:C13)))
Array formulas need to be finalized with Ctrl+Shift+Enter↵. Once entered correctly, they can be filled down like any other formula if necessary.
Array formulas increase calculation load logarithmically as the range(s) they refer to expand. Try to keep excess blank rows to a minimum and avoid full column references.
You can get the average of your "NA" column values in one fairly simple formula like this:
=AVERAGE(IF(
(
($A$2:$A$13>=$F$2)*
($A$2:$A$13<=$F$3)*
ISNUMBER(B2:B13)
)>0,
B2:B13))
entered as an array formula using CtrlShiftEnter↵.
I find this to be a very clear way of writing it, because all your conditions are lined up next to each other. They're "and'ed" using the mathematical operator *; this of course converts TRUE and FALSE values to 1's and 0's, respectively, so when the and'ing is done, I convert them back to TRUE/FALSE using >0. Note that instead of hard-coding your thresholds 7 and 35 (hard-coding literals is usually considered bad practice), I put them in cells.
Same logic for your sum and your count; just replace AVERAGE with SUM and COUNT, respectively:
=SUM(IF((($A$2:$A$13>=$F$2)*($A$2:$A$13<=$F$3)*ISNUMBER(B2:B13))>0,B2:B13))
=COUNT(IF((($A$2:$A$13>=$F$2)*($A$2:$A$13<=$F$3)*ISNUMBER(B2:B13))>0,B2:B13))
though a more succinct formula can also be used for the count:
=SUM(($A$2:$A$13>=$F$2)*($A$2:$A$13<=$F$3)*ISNUMBER(B2:B13))
The same formulas can be used to average/sum/count your "blank" column. Here I just drag-copied them one column to the right (column G), which means that all instances of B2:B13 became C2:C13.
I'd like to use a single formula in excel without using VBA or macros to traverse a 2-dimensional array and produce a single value. The formula would do the following:
First, iterate through every row of the data, calling a function (in my case, MAX) on each row. This will return a column of values. Then call a single function (in my case, SUM) on that column of values. This should return a single value.
In programming terminology, if I am given a 2-dimensional array of values in row-major-order, I'd like to map the function MAX across the 2-d array, and then call SUM on the resulting 1-d array.
Is there a way to do this in excel in a single cell formula?
Thanks so much. Please let me know if I can make this question clearer in any way, or if I should be asking this question somewhere else.
Such requirements are normally achieved with array formulas. But there is no universally usable solution for all such requirements. For functions which are usable with SUBTOTAL, this could be achieved like follows:
{=SUM(SUBTOTAL(4,OFFSET($A$2:$E$2,ROW($A$2:$A$6)-ROW($A$2),0)))}
This is an array formula. Enter the formula in the cell without curly brackets and press [CTRL]+[SHIFT]+[ENTER] then. The curly brackets then should appear automatically.
How it works:
The part ROW($A$2:$A$6) gets a array of row numbers {2,3,4,5,6}. The -ROW($A$2) subtracts the start row, so the resulting array is {0,1,2,3,4}. The OFFSET part then shifts $A$2:$E$2 by {0,1,2,3,4} rows and results in a array of row vectors {$A$2:$E$2, $A$3:$E$3, ..., $A$6:$E$6}. From those the SUBTOTAL gets the MAX values per row and the SUM sums these MAX values.
Instead of SUM as array formula in this case we can also use SUMPRODUCT. This gets its parameters in array context automatically. So with this it is not necessary to enter the formula as array formula:
=SUMPRODUCT(SUBTOTAL(4,OFFSET($A$2:$E$2,ROW($A$2:$A$6)-ROW($A$2),0)))
Imagine I have several (i.e. > 100) column vectors of numbers. Vectors are large with equal length (e.g. 20k items). The vectors are not adjacent, so they don't make a matrix.
What I want, is to get some row-wise computation with the vectors, for instance
For each row what is the first non zero value among all vectors?
or
For each row what is the maximal value among all vectors?
See this simplified example, that should get the maximal value for all vectors, which would be 3 for all row (in reality the displayed value is 1):
It would be easy, if I could copy the vectors as a matrix and get the column of row ranges that spans all vectors for a given row, instead of the column ranges. But that is not the option due to the size of the data. I think it is related to other SO question: Is it possible to have array as an argument to INDIRECT(), so INDIRECT() returns array?.
You can use CHOOSE to combine equal sized columns into a single range, e.g. for your 3 range example:
=CHOOSE({1,2,3},$B$1:$B$4,$B$5:$B$8,$A$3:$A$6)
Then use that directly in a formula, e.g. in G2 copied down to get the MAX in each row for your example
=MAX(INDEX(CHOOSE({1,2,3},$B$1:$B$4,$B$5:$B$8,$A$3:$A$6),F2,0))
or you can define the CHOOSE part as a named range [especially useful if you have 100 ranges], e.g. name that Matrix and use
=MAX(INDEX(Matrix,F2,0))
You need to modify the {1,2,3} part based on the number of ranges, to shortcut when you have 100 ranges you can use
=CHOOSE(TRANSPOSE(ROW(INDIRECT("1:100"))),Range1, Range2.....Range100)
Now needs to be confirmed with CTRL+SHIFT+ENTER
To get the first non-zero value you can use this version
=INDEX(INDEX(Matrix,F2,0),MATCH(TRUE,INDEX(Matrix,F2,0)<>0,0))
also confirmed with CTRL+SHIFT+ENTER
I've found that you actually "can" return an array from INDIRECT().
However it must be in "R1C1" syntax AND you cannot create your R1C1 syntax with a formula (not with something like "R" & ROW() & "C" & COLUMN()".
You have to enter the ROW & COLUMN numbers as absolute and then it works.
Apparently excel puts {} around the numbers when they are returned by ROW() or COLUMN() function, and I guess that's why it doesn't work (try debugging, you'll see).