Search code examples
rdplyrany

How to populate a column based on any() in another column in a grouped data.frame?


I have a dataframe jj:

jj<-data.frame(a=rep(1:3,3),b=c(TRUE,rep(FALSE,4),TRUE,TRUE,FALSE,TRUE))

I want to create a third column that will be true if any of the rows with a particular a have b==TRUE. So I tried this:

group_by(jj,a) %>% mutate(c=any(isTRUE(b)))

But the result I got is this:

# A tibble: 9 x 3
# Groups:   a [3]
      a b     c    
  <int> <lgl> <lgl>
1     1 TRUE  FALSE
2     2 FALSE FALSE
3     3 FALSE FALSE
4     1 FALSE FALSE
5     2 FALSE FALSE
6     3 TRUE  FALSE
7     1 TRUE  FALSE
8     2 FALSE FALSE
9     3 TRUE  FALSE

My expected result should have been this:

# A tibble: 9 x 3
# Groups:   a [3]
      a b     c    
  <int> <lgl> <lgl>
1     1 TRUE  TRUE
2     2 FALSE FALSE
3     3 FALSE TRUE
4     1 FALSE TRUE
5     2 FALSE FALSE
6     3 TRUE  TRUE
7     1 TRUE  TRUE
8     2 FALSE FALSE
9     3 TRUE  TRUE

I don't even understand why I get all FALSE -- it would've made sense if it was all TRUE, and I would think that any() is getting the full column for some reason. What am I missing, and how can I achieve the desired result?


Solution

  • We need to apply any on the logical column and not isTRUE

    jj %>% 
      group_by(a) %>%
      mutate(c = any(b))
    # A tibble: 9 x 3
    # Groups:   a [3]
    #      a b     c    
    #  <int> <lgl> <lgl>
    #1     1 TRUE  TRUE 
    #2     2 FALSE FALSE
    #3     3 FALSE TRUE 
    #4     1 FALSE TRUE 
    #5     2 FALSE FALSE
    #6     3 TRUE  TRUE 
    #7     1 TRUE  TRUE 
    #8     2 FALSE FALSE
    #9     3 TRUE  TRUE 
    

    The reason is that isTRUE is otherwise (from the ?isTRUE)

    is.logical(x) && length(x) == 1 && !is.na(x) && x 
    

    the rhs expression of && will be be evaluated only if the expression lhs are all true

    here, the length(x) equals to 1 is not correct, so it returns FALSE