I have a large series of numbers that I want to convert to a 0 to 10 scale.
I used the following formula to convert the maximum value to 10 and minimum value to 0,
=IF(A1="-","0",MIN(MAX((A1-MIN(A:A))/((MAX(A:A)-MIN(A:A))/11),0),10))
However,I face some problems converting the series where maximum value should be 0 and minimum value should be 10. For example, if column A has the values,
1
4
6
7
8
then 8 should have a value of 0 and 1 should have a value of 10.
Thanks!
Just use the formula =10-B1, where B1 is the cell containing your mentioned formula.
Please note though that your formula has the following flaws:
It is wrong. If you test it with the three numbers 1,2,3 you get 5.5 for the value corresponding to 2. Obviously the correct answer should be 5. This error is caused by the number 11 that you use to divide the (MAX(A:A)-MIN(A:A)). Change it to 10 and everything will work!
It returns #DIV/0! if you have only one number in column A.
It is inefficient because it calls time-expensive functions MAX(A:A) and MIN(A:A) in each and every cell containing this formula. Since these two functions are not dependent on the formula-containing cell, consider using them only once in some other cells and subsequently modify your formula so it contains links to these external cells rather than the functions themselves.
It is hardly maintainable and/or readable. It took me a while to understand how your formula works. Consider separating it into meaningful pieces, place the pieces into separate cells and finally simply link the pieces together in some final - and much smaller - formula.
It is unnecessarily convoluted. There is a much easier formula to achieve the same thing, based on the following:
= 10*B1/C1,
where B1 contains the "distance from minimum", i.e. A1-MIN(A:A), and C1 contains the total length of your range of numbers, i.e. MAX(A:A)-MIN(A:A)
Related
I am trying to make a formula that could count the max sum of any number of consecutive days that I indicate in some cell. Here is the dataset and the formula:
Dataset
The formula that calculates the maximum sum of three consecutive days:
=MAX(IFERROR(INDEX(
INDEX(E2:AI2,0)+
INDEX(F2:AI2,0)+
INDEX(G2:AI2,0),
0),""))
As you can see the number of days here is determined by the number of rows in the formula that start with "Index". The only difference between these rows is the letters (E, F, G). Is there any way I could reference a cell in which I could put a number for those days, instead of adding more rows to this formula?
Another approach avoding use of Offset is to use Scan to generate an array of running totals, then subtract totals which are N elements apart (where N is the number of consecutive cells to be added):
=LET(range,E2:AI2,
length,A1,
runningTotal,SCAN(0,range,LAMBDA(a,b,a+b)),
sequence1,SEQUENCE(1,COLUMNS(range)-length+1,A1),
sequence2,SEQUENCE(1,COLUMNS(range)-length+1,0),
difference,INDEX(runningTotal,sequence1)-IF(sequence2,INDEX(runningTotal,sequence2),0),
MAX(difference))
The answer here was posted by another user on another website, so I will repost it here:
One way to achieve this without relying on a VBA solution would be to use the BYCOL() function (available for Excel for Microsoft 365):
=BYCOL(array, [function])
The array specifies the range to which you want to apply your function, and the function itself is specified in a lambda statement. In the end, you want to get the minimum value of the sum of x consecutive days. Assuming that your data is stored in the range E2:AI2 and the number of consecutive days is stored in cell A1, the function looks like this:
=MIN(BYCOL(E2:AI2,LAMBDA(col,SUM(OFFSET(col,,,,A1)))))
The MIN() part ensures that you get only the smallest sum of the array (all sums of the x consecutive values) returned. The array is simply the range in which your data is stored; it is named in the lambda argument col and consequently used by its name. In your case, you want to apply the sum function for, e.g., x = 4 consecutive days (where 4 is stored in cell A1).
However, with this simple specification, you run into the problem of offsetting beyond cells with values toward the right end of the data. This means that the last sum you get would be 81.8 (value on 31 Jan) + 3 times 0 because the cells are empty. To avoid this, you can combine your function with an IF() statement that replaces the result with an empty cell if the number of empty cells is greater than 0. The adjusted formula looks like this:
=MIN(BYCOL(E2:AI2,
LAMBDA(col,IF(COUNTIF(OFFSET(col,,,,A1),"")>0,"",SUM(OFFSET(col,,,,A1))))))
If you do not have the Microsoft 365 version, there are two approaches that would also work. However, the two approaches are a bit more tedious, especially for cases with multiple days (because the number of days can not really be set automatically; except for potentially constructing the ranges with a combination of ADDRESS() and INDIRECT()), but I would still argue a bit neater than your current specification:
=MIN(INDEX(E2:AF2+F2:AG2+G2:AH2+H2:AI2,0))
=SUMPRODUCT(MIN(E2:AF2+F2:AG2+G2:AH2+H2:AI2))
The idea regarding the ranges is the same in both scenarios, with a shift in the start and end of the range by 1 for each additional day.
Another approach getting to the same result:
=LET(range,E2:AI2,
cons,4,
repeat,COLUMNS(range)-cons+1,
MAX(
BYROW(SEQUENCE(repeat,cons,,1)-INT(SEQUENCE(repeat,cons,0,1/cons))*(cons-1),
LAMBDA(x,SUM(INDEX(range,1,x))))))
This avoids OFFSET (volatile, slowing your file down) and the repeat value, consecutive number and/or the range are easily changeable.
Hope it helps (I answered to the max sum, as stated in the title). Change max to min to get the min sum result.
Edit:
I changed the repeat part in the formula to be dynamic (max number of consecutive columns in range), but you can replace it by a number or a cell reference.
The cons part can also be linked to a cell reference.
Also found a big in my formula which is fixed.
Suppose you have an ordered, indexed list of positive values. These positive values are interrupted by 0 values. I want to determine if a consecutive sub-array exists which is not interrupted by 0 values and whose sum exceeds a certain threshold.
Simple example:
Index, Value
0 0
1 0
2 3
3 4
4 2
5 6
6 0
7 0
8 0
9 2
10 3
11 0
In the above example, the largest consecutive sub-array not interrupted by 0 is from index 2 to index 5 inclusive, and the sum of this sub-array is 15.
Thus, for the following thresholds 20, 10 and 4, the results should be FALSE, TRUE and TRUE respectively.
Note I don't necessarily have to find the largest sub-array, I only have to know if any uninterrupted sub-array sum exceeds the defined threshold.
I suspect this problem is a variation of Kadane's algorithm, but I can't quite figure out how to adjust it.
The added complication is that I have to perform this analysis in Excel or Google Sheets, and I cannot use scripts to do it - only inbuilt formulas.
I'm not sure if this can even be done, but I would be grateful for any input.
Start with
=B2
in c2
then put
=IF(B3=0,0,B3+C2)
in C3 and copy down.
EDIT 1
If you were looking for a Google sheets solution, try something like this:
=ArrayFormula(max(sumif(A2:A,"<="&A2:A,B2:B)-vlookup(A2:A,{if(B2:B=0,A2:A),sumif(A2:A,"<="&A2:A,B2:B)},2)))
Assumes that numbers in column B start with zero: would need to add Iferror if not. It's basically an array formula implementation of #Gary's student's method.
EDIT 2
Here is the Google Sheets formula translated back into Excel. It gives you an alternative if you don't want to use Offset:
=MAX(SUMIF(A2:A13,"<="&A2:A13,B2:B13)-INDEX(SUMIF(A2:A13,"<="&A2:A13,B2:B13),N(IF({1},MATCH(A2:A13,IF(B2:B13=0,A2:A13))))))
(entered as an array formula).
Comment
Maybe the real challenge is to find a formula that works both in Excel and Google sheets because:
Vlookup doesn't work the same way in Excel
The offset/subtotal combination doesn't work in Google sheets
The index/match combination with n(if{1}... doesn't work in Google sheets.
With data in columns A and B, insure column B end with a 0. Then in C2 enter:
=IF(AND(B3=0,B2<>0),SUM(B$1:$B2)-MAX($C$1:C1),"")
and copy downwards:
Column C lists the sums of consecutive non-zeros. In another cell enter something like:
=MAX(C:C)>19
where 19 is the criteria value.
You can avoid the "helper" column by using a VBA UDF.
EDIT#1:
Use this instead:
=IF(AND(B3=0,B2<>0),SUM(B$1:$B2)-SUM($C$1:C1),"")
Thanks to #Tom Sharpe and #Gary's Student for answering the question.
While I admittedly did not specify this in the question, I would prefer to achieve the solution without a helper column because I have to do this operation on 30+ successive columns. I just didn't think it was possible in Excel.
Full credit goes to user XOR LX on the Excelforum for coming up with this solution. It has blown my mind and took me the better part of an hour to wrap my head around, but it is certainly very creative. There is no way I could have come up with it myself. Re-posting it here for the benefit of everyone who is looking into this.
Copy and paste the table from my initial question into an empty Excel sheet such that the headers appear in (A1:B1) and the values appear in (A2:B13).
Then enter this formula as an array formula (ctrl+shift+enter), which gives the max of the sums of all the uninterrupted sub-arrays:
=MAX(SUBTOTAL(9,OFFSET(B2,A2:A14,,-FREQUENCY(IF(B2:B13,A2:A13),IF(B3:B14=0,A2:A13,0))-1)))
Note the deliberate offset to include one additional row below the end of the dataset.
Given a set of values, I want to get the average of the 3 smallest values in one formula.
To do this, I found a similiar recipe for the 3 biggest values on https://exceljet.net/formula/average-top-3-scores
=AVERAGE(LARGE(range,{1,2,3}))
But I'am not able to get this work (doesn't matter if I use SMALL or LARGE).
Here is an example:
By the way, this is LibreOffice Calc but I hope that it behaves like Excel.
If I enter this formula, Calc changes it to =AVERAGE(SMALL(A1:A6;{1,20,3})) (2 has changed to 20).
Even if I change the function type to Array it doesn't work:
What I'am not want is to use auxiliary cells to calc the first, second and third smallest value and averging over this 3 cells.
I have following data in Excel:
A B C
1 Task Name Total Effort (days) %Finished
2 Task 1 5 30
3 Task 2 8 25
4 Task 3 23 18
5 Task 4 32 5
All I want to get is "=SUM(B2*C2 : B5*C5)". But Excel doesn't allow me to do this. How do I achieve my goal?
This is simple with SUMPRODUCT:
=SUMPRODUCT(B2:B5,C2:C5)
To elaborate, while #Olly's answer SUMPRODUCT(B2:B5, C2:C5) is indeed correct, however I got impression from your original post that you are a bit confused about the selectors in hand - I do believe you should study up on it before even copy-pasting any formula.
In excel formulas, if you are refering to a range of cells, you do it by declaring the range from it's starting point, to it's ending point with a colon.
So for example, the green range would be A1:A5, the blue range would be C3:E3 and the yellow range would be F5:G11
Next we have separators, these seperate individual ranges (or cells - even an individual cell is a range itself, a range with a size of 1 cell)
For example with the following range, we would select it as (A1:A2, A5, A7:A8) notice the comma (,) acting as a separator.
Now as to how =SUMPRODUCT actually works, it takes two ranges, pits them side by side. It then does multiply the first cell of the first range with the first cell of the second range and so on. In the end, it adds them all together.
That sounds a bit difficult in words. Here is an illustration
So yes, this actually means the individual values don't even have to be side by side.
Hopefully you understand now not only how your code should look like, but also why your original code didn't work! :)
I am trying to figure out how excel can fill down a column if i make a function like sum(A1:A2), sum(A1:A3) and so on. i have had no luck thus far with successfully filling as what would occur is the following result for the respective cells; sum(A1:A2), sum(A2:A3). I am sure there is a very simple fix but I am not typically an excel user.
While it may be tempting to enter the simple formula =SUM(A$2:A2) into B2 and copy it down, if you're going to sum large ranges this is actually incredibly inefficient on large ranges compared to the formula =SUM(B1,A2)
Why? Let's say you copy =SUM(A$2:A2) down 10 rows.
Your result at row 2 only had to sum 1 number: the number in A2.
Your result at row 3 has to sum 2 numbers: the numbers in A2:A3.
Your result at row 4 has to sum 3 numbers: the numbers in A2:A4.
...
Your result at row 11 has to sum 10 numbers: the numbers in A2:A11.
So how many numbers did Excel have to add in total to produce the answers you calculated in B2:B11?
1+2+3+4+5+6+7+8+9+10 = 55
But if we're using the other approach i.e. =SUM(B1,A2) then all we're doing for each row is adding the number to the left to the previously calculated sum above. So on each row, we sum only two numbers together. Meaning to produce the same 10 answers, the amount of numbers that Excel has to add to produce the exact same totals in B2:B11 are:
2+2+2+2+2+2+2+2+2+2 = 20
Now let's extrapolate that, to some sizeable ranges.
Yikes! So how much does this matter in the real world, given we've all got pretty fast computers good at math?
If you fill rows A2:A100000 with some numbers and then put =SUM(B1,A2) in B2 and fill down, it takes well under a second to calculate on my PC. But if you put =SUM(A$2:A2) instead, it takes almost a minute.
My advice: Get out of the habit of using =SUM(A$2:A2). One day you'll thank me for it.