I have some 15 items which I wish to count how many times it repeats over a series of time. This is highlighted by 1 in that time period. As per the attached pic, the blue area is the data and the yellow is the result that I wish to obtain.
E.g. In occurrence 5, this repeats current record - 1 three times, current record - 2 two times etc. I also do not want to count the current wekks item twice as per the Observation item 14. The results in the yellow have been calculated manually, and the only alternative is to do individual IF statements based upon my knowledge...
EXAMPLE
Is there a formula to do this automatically? I have tried to work with arrays and matching items to check for repeats but cannot work it out.
Update for Clarification: In the Current Occurrence 5 - Obs 1, 6 and 15 came up in Occurrence 4 (Repeats Current -1 or Occurrence 4 - three times), Obs 5 and 8 came up in Occurrence 3 (Repeats Current -2 or Occurrence 4 - two times). (Occurrences are just points in time. Observations might be people having been observed doing something - the number of times is irrelevant, it is just a true or false outcome)
Looking at Occurrence 4, Obs 6 and 9 (Repeats Current -3) or Occurrence 1 two times (my bad I only specified 1 times which might have caused confusion).
I would like the formula to stop searching for prior occurrences once the next recent one has been found eg Obs 14 in Occurrence 3 should stop looking once it finds a repeat in Occurrence 2.
To expand on Edward's answer I used the following formula as intermediate formula:
=IF(AND(ISNUMBER(C7);C7=C8;C8=C9;C9=C10);"-3";IF(AND(ISNUMBER(C7);C7=C8;C8=C9);"-2";IF(AND(ISNUMBER(C7);C7=C8);"-1";"")))
Then use Countif(R3:AF3;"-3") to count the number of -3.
By starting the If constraints at -3 and working your way back, the formula stops automatically when the last match is found.
You can use intermediate calculated cells, which you can hide later if you wish.
Insert 15 columns (1 for each observation) between observations and repeats.
In the first inserted cell create a formula for an individual repeated observation:
=AND(ISNUMBER(B3),B3=B4)
i.e. To be counted as a repeat, the observation must be a number AND the same as the cell immediately below it.
Duplicate this formula horizontally so it calculates across for all 15 observations.
Then create a formula to the right to count the matching observations
=COUNTIF(R3:AF3,TRUE)
Now duplicate the formulas down for all the occurrences.
For current-2 you can reference the cell directly below and to the left, and duplicate this across and down.
For clarity, I have left out your last requiremnet, to stop searching once a match is found. To do this you will need to expand the intermediate formula to take this into account.
Related
Assume we have got an array arr with all initial values 0. Now we are given n operations - an operation consists of two numbers a b. It means that we are adding +1 to the value of arr[a] and adding -1 to the value of arr[b].
Moreover, we can swap numbers in some operations, what means that we will add -1 to arr[a] and +1 to arr[b].
We want to achieve a situation, in which all values of arr are equal to 0 even after all these operations. We are wondering if that is possible, and, if yes, what operations should we swap to achieve that.
Any thoughts on that?
Some example input:
3
1 2
3 2
3 1
should result in
YES
R
N
R
where R means to reverse that operation, and N not to do it.
input:
3
1 2
2 3
3 2
results in answer NO.
Let each of the array element be a vertex in a graph and the operation (a,b) be a edge from vertex a to b (there might be multiple edges between same vertices). Now traveling from the vertex a means decrease array element a and traveling to the vertex a means increase array element a. Now if each vertex has an even number of edges and you find a cyclic path that visits each edge exactly once you will have a zero total sum in the array.
Such a path is called Eulerian cycle (Wikipedia). From the Wikipedia: An undirected graph has an Eulerian cycle if and only if every vertex has even degree, and all of its vertices with nonzero degree belong to a single connected component. As in your case only all the disconnected sub graphs need to have an Eulerian cycle it is enough to count how many times each array index appears and if the count is even for each one of them there is always way to obtain zero total in the array.
If you want to find out which operations to reverse, you need to find one of such paths and check which directions you travel the edges.
Just count the number of times the indices appear. If all indices appear in even numbers, then the answer is YES.
You can prove it by construction. You will need to build a pair list from the original pair list. The goal is to build the list such that you can match every index that appears on the left with an index that appears on the right.
Go from the first pair to the last. For each pair, try to match an index that appears an odd number of times.
For example, in your first example, each index appears twice, so the answer is YES. To build the list, you start with (1,2). Then you look at the pair (3,2) and you know that 2 appears once on the right, so you swap it to have 2 on the left: (2,3). For the last pair, you have (3,1) which matches 1 and 3 that appear only once so far.
Note that at the end, you can always find a matching pair, because each number appears in an even number. Each number should have a match.
In the second example, 2 appears three times. So the answer is NO.
I have a m x m two-dimensional array and I want to randomly select a sequence of n elements. The elements have to be adjacent (not diagonally). What is a good approach here? I though about a depth-first search from a random starting point but that seemed a little bit overkill for such a simple problem.
If I get this right, you are looking for sequence like continuous numbers ?
When i simplyfy this:
9 4 3
0 7 2
5 6 1
So when the 1 is selected, you'd like to have path from 1 to 4 right ? I personally think that Depth-First search would be the best choice. It's not that hard, it's actually pretty simple. Imagine you select number 2. You'll remember position of number 2 and then you can look for lowest numbers until there are any. When you are done with this part, you just do the same for higher numbers.
You have two stacks one for possible ways and another one for final path.
When going through the array, you are just poping from possibilities and pushing right ones into the final stack.
The best approach would be finding the lowest possible number without saving anything and then just looking for higher numbers and storing them so at the end you'll get stack from the highest number to the lowest.
If I get that wrong and you mean just like selecting elements that are "touching" like (from my table) 9 0 7 6, which means that the content doesn't matter, then you can do it simple by picking one number, storing all possibilities (every element around it) and then pick random number from 0 to size of that stored values. When you select one, you remove it from these stored values but you keep them. Then you run this on the new element and you just add these new elements to stored elements so the random will always pick surrounding around these selected numbers.
Ok,. Here, I have a column of values, which are ascending order numbers. At certain points, sequence is broken and 0 's are replacing the values. Its like , 1,2,3,0,0,6,0,8,... in continuous cells of a column. Now, I want another column to be linked to this one, but instead of the zeros, the next non zero number appearing on the sequence should be shown. ie. a link to array which exclude a certain value and skips its place. I want it to be in realtime, either using formulas or using macros. Thank you in advance.
OK I got it now (hopefully)... what you are looking for is doable with a simple "SMALL"-function like:
D2: =IFERROR(SMALL(A:A,COUNTIF(A:A,0)+ROW()-1),"")
E2: =IFERROR(INDEX(B:B,MATCH(D2,A:A,0)),"")
The formulas then simply can be copied down. The -1 is the offset for not starting in row 1 (starting at row 25 would need -24). The COUNTIF is simply for skipping out the 0's.
Should be pretty much self explaining, but if you still have any questions, just ask :)
Starting with a blank or zero in C1, and assuming the list of numbers starts in A2 and numbers aren't repeated, you could look for the next number which is greater than the number above starting in C2:-
=IFERROR(INDEX(A$2:A$10,MATCH(TRUE,INDEX(A$2:A$10>C1,0),0)),"")
Is this what you meant?
I've only just started using arrays (as in yesterday) and have tried ambitiously to use them in a work spreadsheet but am having issues. Details are as follows:
I have a table of data with column R containing a list of room numbers (where each room number can appear more than once and each instance needs to be counted.). I want to then count how many of those room numbers are also in my list in column Z(particular room type).
I can do this by checking each room number individually but was wondering if it was possible to do with this by checking the entire array at once.
I mocked up an array formula to accomplish the task. Probably not the best implementation but it was quick. As always you need to enter an array formula with CTRL + SHIFT + ENTER. Note that I assumed each column had 15 rows and started in row 1.
Count Duplicates Independently
=SUM(1*NOT(ISERROR(MATCH(R1:R15,$Z$1:$Z$15,0))))
Count Duplicates As One
=SUM(IFERROR(1/COUNTIF(R1:R15,R1:R15),0)*NOT(ISERROR(MATCH(R1:R15,$Z$1:$Z$15,0))))
The formula breaks down like so...
IFERROR(1/COUNTIF(R1:R15,R1:R15),0)
Returns 1/(# of occurrences of a given cell value in all of column R). This allows us to sum up 1/3 + 1/3 + 1/3 if a room number is in column R three times (so we only count it once).
NOT(ISERROR(MATCH(R1:R15,$Z$1:$Z$15,0)))
Returns TRUE if the given column R cell value occurs in column Z and FALSE otherwise. When we multiply this time the first part, TRUE becomes 1 and FALSE becomes 0.
=SUM(...)
Sum up all the intermediate products.
Courtesy of #Scott Craner who suggested:
=Sumproduct(COUNTIF(R2:R1709,Z2:Z199))
Thanks also to #Mark Balhoff as well.
I currently use the following array formula to find the most common word or number in a range, ignoring any blank cells:
{=(INDEX(D1:D10,MODE(IF((D1:D10<>"")*ISNA(MATCH(D1:D10,$A$1:$A1,0)),MATCH(D1:D10,D1:D10,0)))))}
I am now looking to do something slightly different. I still want to find the most common word or number in a range, however I now have 2 lists: the first is a list of 'positive' words/numbers and the second is a list of 'negative' words/numbers.
To illustrate using an example: the colour green appears in the 'positive' list 4 times and the colour blue appears twice in the 'positive list', but green appears 3 times in the 'negative' list and blue does not appear at all in the 'negative' list. Using the above formula on the first list would return green as the most common word. However I now want it to take into account that green is not the most common word given the combined lists (i.e. 4 positives - 3 negatives = 1 green, and 2 positives - 0 negatives = 2 blue).
In the below image, using the formula under each list shows green to be the most common word. I would like to combine these lists and cancel out any instances where the colour appears on both instances - so 3 of the greens on the positive list would be cancelled out with the 3 greens on the negative list, leaving only one left.
In essence, I suppose I am trying to create a tally or ledger of some kind where rather than numbers that add or subtract I have words whose frequency is added or subtracted.
Thanks for the help, and apologies if I haven't been too clear in the task!
This should work:
=IF(SUMPRODUCT((MMULT(COUNTIF(OFFSET(B2:B11,,{0,1}),B2:B11),{1;-1})=MAX(MMULT(COUNTIF(OFFSET(B2:B11,,{0,1}),B2:B11),{1;-1})))/COUNTIF(B2:B11,B2:B11&""))>1,"No Favourite",INDEX(B2:B11,MATCH(MAX(MMULT(COUNTIF(OFFSET(B2:B11,,{0,1}),B2:B11),{1;-1})),MMULT(COUNTIF(OFFSET(B2:B11,,{0,1}),B2:B11),{1;-1}),0)))
And for non-contiguous, dynamically-defined ranges, assumed to be stored as Defined Names Positive and Negative, array formula**:
=IF(SUM((COUNTIF(Positive,Positive)-COUNTIF(Negative,Positive)=MAX(COUNTIF(Positive,Positive)-COUNTIF(Negative,Positive)))/COUNTIF(Positive,Positive&""))>1,"No Favourite",INDEX(Positive,MATCH(MAX(COUNTIF(Positive,Positive)-COUNTIF(Negative,Positive)),COUNTIF(Positive,Positive)-COUNTIF(Negative,Positive),0)))
Regards
**Array formulas are not entered in the same way as 'standard' formulas. Instead of pressing just ENTER, you first hold down CTRL and SHIFT, and only then press ENTER. If you've done it correctly, you'll notice Excel puts curly brackets {} around the formula (though do not attempt to manually insert these yourself).
First list your candidates in column D starting at D2
Then in E2 enter:
=COUNTIF(B$2:B$12,D2)-COUNTIF(C$2:C$12,D2)
and copy down.
Finally in F2 enter:
=INDEX(D:D,MATCH(MAX(E:E),E:E,0))
With your data: