I am looking for a tidyverse-solution that can count occurrences of unique values of TF
within groups, id
in the data datatbl
I had a answer without data.table
but it was not using dplyr
. Here is my attempt using dplyr
:
#Remove the NAs
dfr <- df %>% filter(!is.na(TF)) %>%
# group by id
group_by(id) %>%
# Calculate the rle on TF for each group
do(., mrle = rle(.$TF)) %>% mutate(Total=sum(mrle$lengths)) %>%
# Trasform the rle result in a data.frame counting the values after and before changes
do( {
t<- .$mrle
#for each length generate the columns
res <- as.data.frame(lapply(seq_along(t$lengths[-length(t$lengths)]), function(i) {
#before change counts
n1 <- t$lengths[i]
#position the counts
if(i==1) {
before <- 0
} else {
before <- sum(t$lengths[1:i-1])
}
#after change conts
n2 <- t$lengths[i+1]
if(i == (length(t$lengths)-1))
after <- 0
else
after <- .$Total - before - n1 - n2
# assemble the column
c(rep(NA,before),-n1:-1,1:n2, rep(NA,after))
} ))
colnames(res) <- paste0("PM", 1:ncol(res))
#preserve the id
cbind(id=.$id,res)
})
#Join with the original data.frame
res <- df %>% mutate(rn = row_number()) %>% filter(!is.na(TF)) %>% bind_cols(dfr) %>% right_join( df %>% mutate(rn = row_number()) ) %>% select(-rn, -id1)
#Verify
mapply(all.equal, dfa,res)
# id TF PM01 PM02 PM03 PM04 PM05
#TRUE TRUE TRUE TRUE TRUE TRUE TRUE