EXCEL How to write a step function - excel

How do you return different values in a cell based on which range the value entered in another cell comes under? Specifically, I am trying to make a step function.
For example:
IF G2 is ABOVE "0" BUT BELOW "1" THEN display "0.1"
IF G2 is ABOVE "0.99" BUT BELOW "5" THEN display "0.15"
IF G2 is ABOVE "4.99" BUT BELOW "15" THEN display "0.2"
IF G2 is ABOVE "14.99" BUT BELOW "30" THEN display "0.5"
IF G2 is ABOVE "29.99" BUT BELOW "100" THEN display "1.0"
IF G2 is ABOVE "99.99" THEN display "1.30"
So IF G2 was "£18.75" then the cell that this formula is entered in would display "£0.50" based on the value's above.
(bear in mind that this is specific to my spreadsheet and was for calculating prices i.e. 0.99 = £0.99)

Following #oli_taz's suggestion, here is a slightly more robust solution that can deal with any input:
=IF(D4<F4, 0, VLOOKUP(D4,F4:G9,2))
with the range F4:G9:
0 0.1
1 0.15
5 0.2
15 0.5
30 1
100 1.3
and D4 being the value in question, e.g. 18.75 -> result: 0.5
Numbers smaller than 0 will return 0 and numbers larger than 100 will return 1.3.

Nested if's in Excel Are ugly:
=If(G2 < 1, .1, IF(G2 < 5,.15,if(G2 < 15,.2,if(G2 < 30,.5,if(G2 < 100,.1,1.3)))))
That should cover it.

Related

Sum rows in one column between 2 time range

Is there a way to sum values in a column between two different time. The two different hrs are different for different start and end calculation. The formula i used is =SUMIFS(Period,time,">="&Time Range,time, Range,"<="&Time Range) , but the formula returns only the first hour value but the expected result should be between total of start calc and end cal value
time period Cal stat Time Range Expected Result
6:37:02 AM 1 start calc 6:37:02 AM 4
6:37:03 AM 1 no action 0
6:37:04 AM 2 End Calc 6:37:04 AM
6:37:06 AM 1 Start Calc 6:37:06 AM 6
6:37:07 AM 1 no action 0
6:37:08 AM 2 no action 0
6:37:10 AM 1 no action 0
6:37:11 AM 1 End Calc 6:37:11 AM
6:37:12 AM 2 Start Calc 6:37:12 AM 3
6:37:14 AM 1 End Calc 6:37:14 AM
6:37:15 AM 1 no action 0
6:37:16 AM 1 no action 0
6:37:17 AM 2 no action 0
6:37:19 AM 2 no action 0
I don't know about doing it with SUMIFS.
However, with INDEX(MATCH(…, you can construct a formula that will sum from the current row to the next "end Calc", and use an IF(… to only show results in the start calc rows.
E2: =IF(C2="start calc", SUM( INDEX(B2:$B$15,1): INDEX(B2:$B$15,MATCH(TRUE,C2:$C$15="end Calc",0))),"")
Fill the formula down as far as needed
The $15 row numbers in the formula can be changed to any row that is at least as large as your expected table, but be sure it remains an absolute address.
e.g: =IF(C2="start calc", SUM( INDEX(B2:$B$1500,1): INDEX(B2:$B$1500,MATCH(TRUE,C2:$C$1500="end Calc",0))),"")

generate random numbers between 0 and 1 in 10 cells in the row , in which the sum of the random number always equal to 7

How can I generate random numbers 0 or 1 in 10 cells in the row, in which the sum of the random number is always equal to 7?
enter image description here
Here's a way to get seven "1"s and three "0"s in random order using RAND and RANK
In A1:J1: =RAND()
In A2:J2: =IF(RANK(A1,$A$1:$J$1,1)>3,1,0)
Available here is a version that I really think works! https://www.dropbox.com/s/ec431fu0h0fhb5i/RandomNumbers.xlsx?dl=0
And here's the '0 and 1' version (sheet 2 at the above link):
De-dup Rankings Randoms First Cut Sorted
0.47999002 7 0.479992063 1 1
0.68823003 3 0.688233075 1 1
0.07594004 9 0.075938331 1 1
0.02077005 10 0.020766892 1 0
0.69217006 2 0.692170173 1 0
0.73355007 1 0.733549516 1 1
0.51546008 6 0.515462872 1 1
0.62308009 4 0.623078278 0
0.33033001 8 0.330331577 1
0.561260011 5 0.561260557 1
Formulae for columns A-C exactly as before, D is just 7 1's, E is:
=VLOOKUP(ROW(E2)-1,B$1:D$11,3,FALSE)
Assuming that you want a list of positive random numbers that add to 7 you can use this following method.
Enter a 0 in the top-left cell (Blue Cell).
Enter =RAND()*7 into the next 9 cells below the 0 (Orange Cells).
Enter a 7 in the cell below the 9 random values (Blue Cell).
Copy the 9 random values and paste-special-values over top to turn the formulas into values.
Sort just these 9 cells in ascending order
In the cell just to the right of the first random value put a formula that subtracts the cell to the left and one above from the cell to the left (Yellow Cells).
Repeat this formula down to the cell next to the 7 that was typed in.
Sum the values in the second column (Green Cell).
That should give you 10 random values whose sum is exactly 7.
The only issue is that getting the values to be between 0 and 1 will take a bit of trial and error.
It appears that trial and error may not be practical. It's about a one in 2,710 times that this list will contain only numbers between 0 and 1. Not overly practical. Sorry.
To answer the question in the post, enter this in A1:J1 as an array formula (ctrl+shift+enter):
=1-(TRANSPOSE(MOD(SMALL(RANDBETWEEN(0,1e12*(ROW(INDIRECT("1:10"))>0))+(ROW(INDIRECT("1:10"))-1)/10,ROW(INDIRECT("1:10"))),1))>0.65)
To answer the question in the post title, do the following:
In A1:J1 enter:
=RAND()
In K1 enter:
=IF(SUM(A1:J1)<7,(7-SUM(A1:J1))/(COUNT(A1:J1)-7),7/SUM(A1:J1))
In L1 enter:
=IF(SUM($A1:$J1)<7,(A1+$K1)/($K1+1),A1*$K1)
Fill over to U1.
I believe the 10 numbers generated will be identically distributed in [0,1), but obviously not uniformly (I'm fairly certain the distribution does not have a name). The numbers can't be considered independent. A few statistics on the distribution:
Mean: 0.7 (as expected)
The other statistics are estimated from 10,000 simulations:
Variance: 0.0295
Kurtosis: -0.648
Skewness: -0.192
Think of it as drawing a sample of size 7 from the set {1, 2, ..., 10}. The 1s correspond to the numbers chosen for inclusion in the sample. Here is some VBA code which generates such samples:
Function sample(n As Long, k As Long) As Variant
'returns a variant of length n
'consisting of k 1s and n-k 0s
'thought of as a sample of {1,...,n} of size k
Dim v As Variant 'vector to hold sample
Dim numbers As Variant
Dim i As Long, j As Long, temp As Long
ReDim v(1 To n)
ReDim numbers(1 To n)
For i = 1 To n
v(i) = 0
numbers(i) = i
Next i
'do k steps of a Fisher-Yates shuffle on numbers
For i = 1 To Application.WorksheetFunction.Min(k, n - 1)
j = Application.WorksheetFunction.RandBetween(i, n)
If i < j Then 'swap
temp = numbers(i)
numbers(i) = numbers(j)
numbers(j) = temp
End If
Next i
'now use the first k elements of the partially shuffled array:
For i = 1 To k
v(numbers(i)) = 1
Next i
sample = v
End Function
Used like: Range("A1:J1").Value = sample(10,7)
Using a bit of brute force, I think I've got a workable solution to the original version of the question which asked for random numbers between 0 and 1.
Cells A1 to A9:
=rand()
Cell A10:
=7-sum(A1:A9)
Now you have 10 numbers that add up to 7, but the last one is probably not in the range 0 to 1. To deal with that, just recalculate the sheet to generate new random numbers until that last value is within range. It takes about 25 recalculations to have a ~95% chance that one of them will be within range, so it could take a while. A little VBA can do that for you very quickly:
Sub rand7()
While Range("A10").Value > 1 Or Range("A10").Value < 0
ActiveSheet.Calculate
Wend
End Sub

Excel | Index Match |

I require your assistance on the following:
Lets say we got 3 different groups: (A,B,C)
And we have a few value ranges within each group:
(Eg. A has 0 - 100, 101 - 200 while B has 0 - 200, 201 - 400 and C has 0 - 300, 301 - 600.)
At the end, for each group that falls under whatever range they have, they will be assigned a final number.
(Eg.
[A,95] = 0.5 / [A,101] = 1.0
[B,95] = 1.5 / [B,205] = 3.0
[C,95] = 4.5 / [C,308] = 6.0)
Currently i have my index match formula as follows:
"=INDEX(finalnumber!F2:F29,MATCH(C11&C25,Group!A2:A29&valuerange!D2:D29,0))"
I keep getting a #N/A response.
I have also created an array table as follows:
enter image description here
Group Range Final Number
A 0 - 100 0.50
A 101 - 200 1.00
B 0 - 200 1.50
B 201 - 400 3.00
C 0 - 300 4.50
C 301 - 600 6.00
Pls help! Many thanks in advance!
You can use the following (you will need to tailor to your layout). I have assumed A and 95, for example, are in separate cells as you concatenate cells in your formula to do your lookup.
=IF(AND(ISERROR(INDEX(OFFSET(INDEX(C:C,H2),,,I2-H2+1,1),MATCH(VLOOKUP(G2,LEFT(OFFSET(INDEX(B:B,H2),,,I2-H2+1,1),FIND("-",OFFSET(INDEX(B:B,H2),,,I2-H2+1,1))-1)*1,TRUE),LEFT(OFFSET(INDEX(B:B,H2),,,I2-H2+1,1),FIND("-",OFFSET(INDEX(B:B,H2),,,I2-H2+1,1))-1)*1,0))),INDEX(A:A,COUNTA(A:A)+1)=F2,G2>=1*LEFT(INDEX(B:B,COUNTA(A:A)+1),FIND("-",INDEX(B:B,COUNTA(A:A)+1))-1),G2<=1*RIGHT(INDEX(B:B,COUNTA(A:A)+1),LEN(INDEX(B:B,COUNTA(A:A)+1)) - FIND("-",INDEX(B:B,COUNTA(A:A)+1)))),INDEX(C:C,COUNTA(A:A)+1),INDEX(OFFSET(INDEX(C:C,H2),,,I2-H2+1,1),MATCH(VLOOKUP(G2,LEFT(OFFSET(INDEX(B:B,H2),,,I2-H2+1,1),FIND("-",OFFSET(INDEX(B:B,H2),,,I2-H2+1,1))-1)*1,TRUE),LEFT(OFFSET(INDEX(B:B,H2),,,I2-H2+1,1),FIND("-",OFFSET(INDEX(B:B,H2),,,I2-H2+1,1))-1)*1,0)))
This is entered as an array formula with Ctrl+ Shift+ Enter
Formulas in helper cells (to keep overall formula more legible):
H2 is =MATCH(F2,A:A,0) ' finds the first match for the letter e.g. A
I2 is =MAX(IF(A:A=F2,ROW(A:A)-ROW(INDEX(A:A,1,1))+1)) ' finds the last match for the letter e.g. A. This is entered with Ctrl+ Shift+ Enter i.e. an array formula.
Data layout
Example run:
Notes:
You might want to wrap the whole thing in an IFERROR( formula, "") to hide any not found error messages.
I'm unclear why you require four separate worksheets for this operation. For simplicity in demonstrating, I've put your lookup table on the same worksheet as the values to lookup.
=SUMPRODUCT(I$2:I$7, (G$2:G$7=LEFT(A2))*(--REPLACE(H$2:H$7, FIND(" - ", H$2:H$7), 9, TEXT(,))<=--MID(A2, 3, 9))*
(--REPLACE(H$2:H$7, 1, FIND(" - ", H$2:H$7)+1, TEXT(,))>=--MID(A2, 3, 9)))

Getting average of top 1/3, second 1/3, and last 1/3 of values in column

I have a column with numbers and a reference column. I'm trying to separate the numbers column into first third, second third, and last third and take the average of each.
Values Ref column
1.7 cow
2.3 cow
2.6 cow
1.8 sheep
1.3 sheep
2.2 sheep
1.5 sheep
1.2 sheep
2.3 sheep
1.5 goose
2.5 goose
So, for example, the average of the first two values for "sheep", second two, and last two. In other words, I want to take the average of each 1/3 of cells adjacent to "sheep".
Add a column to cumulatively count the instances of the word you're looking at, then check that row number in your AVERAGE.
C2 = =CountIf($B$2:$B2, $B2) and fill down => values should be {1,2,3,1,2,3,4,5,6,1,2}
E1 = sheep
E2 = =CountIf($B:$B, $E$1) => 6
E3 = {=Average(If(($B:$B = $E$1) * ($C:$C <= $E$2 / 3), $A:$A))} (note this is an array formula, as designated by the {} around it) => 1.55
E3 = {=Average(If(($B:$B = $E$1) * ($C:$C > $E$2 / 3) * ($C:$C <= 2 * $E$2 / 3), $A:$A))} => 1.85
E3 = {=Average(If(($B:$B = $E$1) * ($C:$C > 2 * $E$2 / 3), $A:$A))} => 1.75
Array formulas, if I remember correctly, are entered the same as normal formulas (don't include the {}, that gets entered automatically), but you press Ctrl (and possibly Shift) with Enter when you finish.
NB - these look at the entire column. You can speed them up by changing $A:$A to $A$2:$A$12 (likewise for $B:$B and $C:$C). Just bear in mind that for any data you append to this list, you'll need to update the formulas; but you can insert data into the middle of the list and it will update them automatically.
use a formula like this:
=AVERAGE(INDEX(A:A,MATCH($D$2,B:B,0)+(D3-1)*COUNTIF(B:B,$D$2)/3):INDEX(A:A,MATCH($D$2,B:B,0)+((D3)*COUNTIF(B:B,$D$2)/3)-1))
This does require that the ref column be sorted and like references grouped.
This array formula will return the averages even if not sorted:
=AVERAGE(INDEX(INDEX(A:A,N(IF({1},MODE.MULT(IF($B$1:$B$12=$D$2,ROW($A$1:$A$12)*{1,1}))))),N(IF({1},ROW(INDEX(A:A,1+(D3-1)*COUNTIF(B:B,$D$2)/3):INDEX(A:A,D3*COUNTIF(B:B,$D$2)/3))))))
array formula need to be entered with Ctrl-Shift-enter instead of Enter when exiting edit mode.
Well supposing there were 7 sheep values and you wanted to do a weighted mean (e.g. the first mean would be calculated from the first two sheep plus a third of the third one)?
I have attempted a general solution for this dividing any number of animals into any number of fractions and finding their average values. My approach is to use the elegant overlap formula from #Barry Houdini as used here and work out the overlap between the intervals (in the case of 7 animals divided into 3):
0 to 2.33
2.33 to 4.67
4.67 to 7
and the numbers of the animals
0 to 1
1 to 2
2 to 3
and so on.
In H4
=IF(ROWS($1:1)<=$H$2,ROWS($1:1)/$H$2*COUNTIF(B$2:B$16,$G$2),"")
In G4
=IF(H4="","",H4-COUNTIF(B$2:B$16,$G$2)/$H$2)
The main formula in I4 is
=IF(H4="","",SUM(TEXT(IF(C$2:C$16<H4,C$2:C$16,H4)-IF((C$2:C$16-1)>G4,C$2:C$16-1,G4),"general;\0")
*A$2:A$16*(B$2:B$16=$G$2))/(COUNTIF(B$2:B$16,$G$2)/$H$2))
entered as an array formula.
The fractions can be changed to halves, quarters etc. by changing the number in H2.

complex rounding decimals in excel spreadsheet

Have created formula for example =(E2+(G2*37))/290 which returns decimals based on data entered but can't work out how to round the answer to get the following:
If 0 to 0.39 round to 0
If 0.4 to 0.89 round to 0.5
If 0.9 to 1.39 round to 1
If 1.4 to 1.89 round to 1.5
If 1.9 to 2.39 round to 2 etc
Hope my question makes sense. Thanks
Your custom rounding is simply rounding to the nearest 0.5.....but with an "offset" of 0.15. With value to be rounded in A1 you can do that with a simple formula, i.e.
=ROUND(A1*2-0.3,0)/2
or with your calculation in place of A1 that becomes
=ROUND((E2+G2*37)/290*2-0.3,0)/2
It's a bit convoluted but this should work:
=IF(A1 + 0.1 - ROUNDDOWN(A1+0.1;0) < 0.5; ROUNDDOWN(A1+0.1;0); ROUNDDOWN(A1+0.1;0) + 0.5)
where A1 is the cell you want to round.
e.g.
N.B.
This works only for positive numbers.
Ranges are actually:
[0, 0.39999999...] [0.4 , 0.8999999...] ...
or equally:
[0, 0.4) [0.4 , 0.9) ...
You could define a VBA function to do this for you:
Public Function CustomRound(number As Double)
Dim result As Double, fraction As Double
fraction = number - Int(number)
If number <= 0.39 Then
result = 0
ElseIf fraction >= 0.4 And fraction <= 0.9 Then
result = Int(number) + 0.5
Else
result = Round(number, 0)
End If
CustomRound = result
End Function
You would call this as follows:
=CustomRound((E2+(G2*37))/290)
Example:
=CustomRound(0.23) // 0
=CustomRound(1.58) //1.5
=CustomRound(2.12) //2

Resources