I am attempting to identify a subset of a range based on TRUE FALSE statements. An example is in the following chart below.
FALSE FALSE 1.21147
TRUE FALSE 1.20984
FALSE FALSE 1.21083
FALSE FALSE 1.210315
FALSE TRUE 1.21151
FALSE FALSE 1.21335
FALSE FALSE 1.213515
FALSE FALSE 1.212435
TRUE FALSE 1.212125
FALSE FALSE 1.21226
In this scenario I want a subset to be identified based on alternating TRUE statements. In the left side column the first TRUE statement would trigger the beginning of the subset an the TRUE statement in the second column would trigger the end of the subset. I then want to use a simple max function to identify the MAX in the third column. I would use an IF statement to determine whether or not the first TRUE statement is correct however, i am unable to figure out how to identify the subset of the range based on the TRUE statement in the second column. I also want to know whether or not this works from going from the top to the bottom if the statement could possible work going the bottom to the top. Any help would be most appreciated.
Part 1 can be done using a combination of MATCH, OFFSET and MAX
For this example I've assumed your data is located starting at cell A2.
For the sake of clarity I use some intermediate results in cells E1:E4. If you prefer a single formula, simply merge the intermediate formula into the final formula
Cell E2 = position of first TRUE in column A
=MATCH(TRUE,A2:A11,0)
Cell E3 = position of first TRUE in column B
=MATCH(TRUE,B2:B11,0)
Result formula, Max value in column C between the rows found in E2 and E3 (inclusive)
=MAX(OFFSET($C$1,E2,0,E3-E2+1,1))
Part 2 is more tricky: I don't think you can search up a range for a value. However, looking at your data it may be OK to search down for the second TRUE? If this is OK then:
Cell E4 = position of second TRUE in column A
=MATCH(TRUE,OFFSET(A2:A11,E2,0),0)
Or this, entered as an array formula (Insipred by Barry) which will get the last TRUE in the column
=MATCH(2, 1/(A2:A11=TRUE),1)
Result formula, Max value in column C between the rows found in E3 and E4 (inclusive)
=MAX(OFFSET($C$1,E3,0,E4+E2-E3+1,1))
your part about traversing the table from the bottom up confused me, and also don't know if you can have more than one subset, since you're penultimate row seems to be the opening of a new subset that is not closed. Anyway, hope that this helps. I'm assuming you don't want to use macros, in which case it would be trivial. What you can do is pad the top of the data set with an row that contains FALSE, FALSE, 0, 0, and add this formula to a fourth column starting with the first row of your set:
=IF(AND(NOT(A2),NOT(B2),OR(D1=0,AND(NOT(A1),B1))),0,C1)
That's assuming that your first row is row 2, and row 1 is used for the padding. A, B, and C are the three columns in your example, and D will print the value of the third column if it's within a subset, or zero if is not, so that you can easily calculate max() or whatever you want to do. I looks like this:
Related
Apologies for the confusing title; I will explain my issue more clearly and detailed here.
So I have a list of booleans that includes a repetitive pattern, and I am trying to calculate the factor by which it repeats. The list will always begin with an unknown number of FALSE values before it begins the cycle and will always end with a TRUE followed by an unknown, but large number of FALSE values.
An example list:
FALSE
FALSE
TRUE
FALSE
FALSE
FALSE
TRUE
FALSE
FALSE
FALSE
TRUE
FALSE
FALSE
FALSE
FALSE
FALSE
FALSE
In this case, the factor of repetition I would like is 4 since the pattern repeats every 4 rows (excluding the beginning and end of the list).
I have tried a couple of methods of writing formulas to come up with 4 as the answer including uses of counts, some simple vlookups, and an offset attempt. So far, I have been unable to get a working formula. My guess is that the Indirect function may be of use here, but I haven't been able to wrap my head around the logic of using it yet.
In terms of a general strategy, I'm guessing that if I can find the indices of the rows of the first and second TRUE values, I can simply subtract them to find the repetition factor. (I can easily implement a row number or cell reference column into my spreadsheet if that would help at all too.)
Thanks in advance for any insight!
Try this formula:
=AGGREGATE(15,6,ROW($A$1:$A$17)/($A$1:$A$17),2)-MATCH(TRUE,$A$1:$A$17,0)
The MATCH finds the first row in which there is a TRUE.
The AGGREGATE is working like the SMALL(IF()) Function. when the cell is FALSE it will return a division by 0 error and the 6 in the function overlooks the errors. So the array in which the AGGREGATE is going to pull the second lowest row number is on those rows in which the cell is TRUE.
Edit
Here is a non array formula that does it also, based loosely on #GaryStudents answer:
=MATCH(TRUE,INDEX(A:A,MATCH(TRUE,A:A,0)+1):A1040000,0)
Get the "distance" between two consecutive occurrences of TRUE:
In C1 enter:
=MATCH("TRUE",A:A,0)
and in C2:
=MATCH("TRUE",INDIRECT("A" & C1+1 & ":A9999"),0)+C1
finally in C3:
=C2-C1
I looking for the formula for column A (TRUE or FALSE). I check if column "C" contain "ERROR" text. Row number 2 (cell "C2") contain "ERROR" word, so the formula put "TRUE" in column "A". For now I have a formula per line: =ESTNUM(CHERCHE("ERROR";$C2)) in french or =ISNUMBER(SEARCH("ERROR";$C2))
FALSE DPS-14 OK
TRUE DPS-14 ERROR
FALSE DPS-15 OK
FALSE DPS-14 OK
I want add a condition to my formula. If a element from column "B" have a "TRUE" on column "A" then change (to "TRUE") for all same element. DPS-14 (row 2 is TRUE), also put "TRUE" on row 1 dans 3 because row 1, 2 and 3 are the same value on column "B".
TRUE DPS-14 OK
TRUE DPS-14 ERROR
FALSE DPS-15 OK
TRUE DPS-14 OK
I would solve this with a quick COUNTIFS.
=COUNTIFS($B$2:$B$5, B2, $C$2:$C$5, "ERROR") > 0
Here's a Picture!
Basically, it just takes the current value on the line you're on, checks through the whole range for other values like itself, and then counts the number of ERROR's associated with that value. If it's greater than zero, you've got an error in at least one spot, so the record has an error.
There's a second easy option. If you can sort your data, sort first by the ID, then by whether or not it's an Error or OK (Descending). Then, if you call an index/match on the OK/ERROR column, and it's ERROR, you know it needs to be bool TRUE for all records.
That looks like this!
I know that in your data, that column doesn't literally say ERROR, so you'll need to modify this to either make a helper column to extract which records have ERROR values, or use an array formula with your other formulas. I'd recommend option 1, as it is a higher performance solution and more likely to be understood by other people looking at your work.
I'm working with data sets that increase until they hit a peak and then quickly drop to zero; I want to find the location of that first zero after the peak as that will give me the failure time. However, the values leading up to the peak sometimes contain zero, and my current formula is returning the times for those. An example value set would be either something like [1;1;2;6;7;10;9;0;0;0] or something like [-1;-1;0;4;7;11;10;0;0;0].
We'll say the Time column is A and the Values column is B. I've calculated the minimum value after the peak with:
=MIN(OFFSET(B1,MATCH(MAX(B2:B4001),B:B,0),0,(4001-MATCH(MAX(B2:B4001),B:B,0))))
Using that as a helper cell, I'm retrieving the time at which this value occurs with:
=IF(*min_after_peak*>0,"PASS",INDEX(A:A,MATCH(*min_after_peak*,B:B,0)))
Side note - the "peak" lasts for more than one time measurement and can fluctuate slightly, so if the minimum after the peak is positive that means the sample didn't fail. The minimum after the peak is always either positive or zero (pass or fail, respectively).
Problem is, I don't know how to get MATCH to look at only values after the peak, or if that's even the right way to go.
Any thoughts on how to get the time corresponding to the first zero after the peak?
Assuming your data is in paired columns (starting in A1) please try:
=INDEX(A1:A10,MATCH(0,INDIRECT(CHAR(COLUMN()+65)&MATCH(MAX(B1:B10),B1:B10,0)&":"&CHAR(COLUMN()+65)&"10"),0)+MATCH(MAX(B1:B10),B1:B10,0)-1)
I created a spreadsheet with your first set of data.
0 ispeak peakExists peakAndZero
1 TRUE TRUE FALSE
1 FALSE TRUE FALSE
2 TRUE TRUE FALSE
6 TRUE TRUE FALSE
7 TRUE TRUE FALSE
10 TRUE TRUE FALSE
9 FALSE TRUE FALSE
0 FALSE TRUE TRUE
0 FALSE TRUE TRUE
0 FALSE TRUE TRUE
I added a 0 in a1 and headers in B1, C1, and D1.
In the first row of the isPeak column, that is B2, I added =IF(AND(A2>A1,A2>0),TRUE,FALSE). This puts a true in the cell if the value to the left (A2) is greater than the previous (A1) AND it is greater than 0.
In the first row of the peakExists column, that is C2, I added =OR($B$2:B2). This puts a true in the cell if any of the previous from b2 (absolute) to my row has even a single true.
In the first row of the peakAndZero column, that is D2, I added =AND(C2,A2=0). This puts a true in the cell if a peak exists and the value is a 0.
It looks like you know how to create the index of the row and you know how to select the lowest one with a true in peakAndZero, so I will leave this as an exercise for the OP.
Came up with an adaption to my original formula that avoids helper columns (I have several hundred data sets for this project). Used OFFSET to set an after-peak range in MATCH:
=IF(min_after_peak>0,"PASS",INDEX(A:A,MATCH(MAX(B2:B4001),B:B,0)+MATCH(min_after_peak,OFFSET(B1,MATCH(MAX(B2:B4001),B:B,0),0,(3603-MATCH(MAX(B2:B4001),B:B,0))),0)))
To make it slightly easier to read:
=IF(min_after_peak>0,"PASS",INDEX(A:A,peak_row+MATCH(min_after_peak,OFFSET(B1,peak_row,0,(4001-peak_row)),0)))
where
peak_row = MATCH(MAX(B2:B4001),B:B,0)
I'm trying to find a way to do a reverse match in Excel. I have a column of TRUE/FALSE statements and I need to find a way to find both a match and a reverse match within this one column to find the difference between TRUE statements in both directions.
True
False
False
False
True
False
False
True
In this scenario from the perspective of the middle True statement the normal MATCH function going down would return a number of 4. I am trying to find an additional match function that would look upward to the TRUE statement and return a value of 5
Quick and dirty:
A1:A7: TRUE/FALSE
A8: Array formula: {=LARGE(IF(A1:A7=TRUE;ROW(A1:A7);"");1)}
The result will be the row number of the nearest TRUE from below.
The formula is inserted by Shift-Ctrl-Enter in a formula window. Curled brackets are inserted by Excel, not by a user.
If you need the shift from the last TRUE:
{=LARGE(IF(A1:A7=TRUE;ROW(A1:A7);"");2)}
Changing the last number in the formula moves you to the n-th TRUE from below.
Replacing LARGE with SMALL will give the row numbers from above. So it would possible to find the shift between relevant combinations by combining the formulae.
Here is the array I have:
{=MIN(IF('APRIL 2011'!E3:E999<>"",'APRIL 2011'!E3:E999
*('APRIL 2011'!E3:E999*('APRIL 2011'!D3:D999='APRIL TOTALS'!A2))))}
It still returns zeroes with empty cells!
You can use the ISBLANK() function to test for blank cells. IF cell A1 is blank, then =A1="" evaluates to true, and so does =A1=0
I don't know of an expression to return a blank value to a cell, so I use "" instead, like this:
=IF(ISBLANK([expression]), "", [expression])
Nest your conditions. You are trying to mashup IF criteria with (VALUE)*(TRUE/FALSE) and the when the TRUE/FALSE is FALSE, you are multiplying by zero. In this way, you are discarding blank cells but artificially seeding your result set with zeroes for every row where column D <> 'APRIL TOTALS'!A2.
As an array formula,
=MIN(IF('APRIL 2011'!E3:E999<>"", IF('APRIL 2011'!D3:D999='APRIL TOTALS'!A2, 'APRIL 2011'!E3:E999)))
Array formulas need to be finalized with Ctrl+Shift+Enter↵ (but you already knew that!).
The issue with your formula is that you are returning the minimum of an array of Boolean products. Because these are Boolean products, products with a FALSE multiplier (the ones you intend to exclude) are counted as 0.
I see a way around this as long as Column E contains no zero values. I've made two big changes to your original formula:
To remove the Boolean multiplier problem, I've used an IF statement to choose multipliers instead of 1 and 0 for TRUE and FALSE. TRUE is still 1, but FALSE is now a large number -- make it larger than any value in Column E. This way, the blank entries will only be the minimum value if they are the only value.
To take care of the case where the large number will be returned, I've made it such that the Minimum value is calculated only if there are non-blank values in Col E for Col D values = A2. If there are no such values, "" is returned.
{=IF(COUNT(IF('APRIL 2011'!D3:D999='APRIL TOTALS'!A2,
IF('APRIL2011'!E3:E999<>"",'APRIL2011'!D3:D999)))=0,""
MIN(IF('APRIL2011'!E3:E999<>"",'APRIL2011'!E3:E999,10000000000)
*IF('APRIL 2011'!D3:D999='APRIL TOTALS'!A2,1,1000000000000)))}