Reputation: 45
I would like to count how many times I see two consecutive TRUE values in R. For example,
x <- c(T,F,T,T,F,F,T,F,T,F)
x
[1] TRUE FALSE TRUE TRUE FALSE FALSE TRUE FALSE TRUE FALSE
It would count 1 since there is a TRUE at position 3 and TRUE at position 4. If there are more than 2 consecutive TRUE, then I just want to count it only once, ie this vector
x <- c(T,F,T,T,T,F,T,F,T,F)
x
[1] TRUE FALSE TRUE TRUE TRUE FALSE TRUE FALSE TRUE FALSE
would still count 1. I started with looking at rle()
but I got stuck. Any help would be greatly appreciated. Thanks!
Upvotes: 3
Views: 3820
Reputation: 886968
Here is another option with rleid
from data.table
. The rleid
gives a unique id to adjacent elements that are different, multiply with x, to convert the elements that corresponds to the FALSE
in original vector to 0, get the frequency with tabulate
convert to a logical vector (==2
) and get the sum
.
library(data.table)
sum(tabulate(rleid(x)*x)==2)
#[1] 1
Upvotes: 0
Reputation: 12937
You could also use cumsum
and split
for that purpose as follows:
x <- c(TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE,
TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE)
sum(lapply(split(x, cumsum(!x)), sum)>=2)
#[1] 3
Upvotes: 1
Reputation: 4866
This should work:
with(rle(x), sum(lengths[values] >= 2))
Explanation:
As you are using Booleans, you can take profit of it. rle(x)$lengths
will return how many consecutive times TRUE
or FALSE
happen in the vector. Example
x <- c(T,F,T,T,T,F,T,F,T,F,T,T)
rle(x)$lengths
[1] 1 1 3 1 1 1 1 1 2
Now you only want those values in this vector that correspond to TRUE
s. rle(x)$values
returns a vector with the order of appearance. Example:
rle(x)$values
[1] TRUE FALSE TRUE FALSE TRUE FALSE TRUE FALSE TRUE
You can use this to only get the TRUE
s in the lengths
vector:
rle(x)$lengths[rle(x)$values]
[1] 1 3 1 1 2
And the last step should be obvious: count how many of this values are grater or equal than 2. All together (with performance improvement):
with(rle(x), sum(lengths[values] >= 2))
[1] 2
Upvotes: 11