Home > Blockchain >  case_when where replaced columns have different types
case_when where replaced columns have different types

Time:11-23

I am working on the following problem which requires to use case_when. However, I encounter the error message Error: must be a logical vector, not a double vector because the replaced columns are not the same type (some logical and some double due to bind_rows). I am looking for a clean solution to get the desired output.

#set empty dataframe with column names
df <- setNames(data.frame(matrix(ncol = 5, nrow = 0)), c("a", "b", "c","d","e")) 
df_subset <- data.frame(b=c(1,2))
df1 <- bind_rows(df,df_subset)%>%mutate(type="b")
df1
   a b  c  d  e type
1 NA 1 NA NA NA    b
2 NA 2 NA NA NA    b

df1%>%mutate(result=case_when(type=="a"~a,
                              type=="b"~b,
                              type=="c"~c,
                              type=="d"~d,
                              type=="e"~e,
                              T~NA_real_))

Error: must be a logical vector, not a double vector

Expected output: (Note: I do not always know if column b has values)

df1%>%mutate(a=NA_real_,
             c=NA_real_,
             d=NA_real_,
             e=NA_real_,
             result=case_when(type=="a"~a,
                              type=="b"~b,
                              type=="c"~c,
                              type=="d"~d,
                              type=="e"~e,
                              T~NA_real_))

#desired output
   a b  c  d  e type result
1 NA 1 NA NA NA    b      1
2 NA 2 NA NA NA    b      2

CodePudding user response:

I think that you might be looking for:

df1 %>%
 rowwise() %>%
 mutate(result = get(type))

  a         b c     d     e     type  result
  <lgl> <dbl> <lgl> <lgl> <lgl> <chr>  <dbl>
1 NA        1 NA    NA    NA    b          1
2 NA        2 NA    NA    NA    b          2

CodePudding user response:

This is because the way you created the matrix results in a logical matrix. Then b column was created as an integer column.

Inspect this with str(df1).

Then case_when() sees the mixed types. a being logical, and b being integer. As seen in the error message.

See the documentation in the details section of ?matrix for more.

The solution is to make an integer matrix at the beginning. Then your original code works.

df <- as.data.frame(matrix(NA_integer_, nrow=2, ncol=5, dimnames=list(1:2, letters[1:5])))
df$b <- c(1,2)
df$type <- c("b","b")
df %>% mutate(result=case_when(type=="a"~a,
                               type=="b"~b,
                               type=="c"~c,
                               type=="d"~d,
                               type=="e"~e,
                               T~NA_integer_))
                          
#   a b  c  d  e type result
#1 NA 1 NA NA NA    b      1
#2 NA 2 NA NA NA    b      2

CodePudding user response:

Your code works fine if you fix all types to numeric.

dplyr Solution

library(dplyr)

df1 %>% 
  mutate(across(a:e, as.numeric)) %>%  # this is the fix
  mutate(result=case_when(type=="a"~a,
                          type=="b"~b,
                          type=="c"~c,
                          type=="d"~d,
                          type=="e"~e,
                          T~NA_real_))

Output

#>    a b  c  d  e type result
#> 1 NA 1 NA NA NA    b      1
#> 2 NA 2 NA NA NA    b      2

CodePudding user response:

We may use

library(dplyr)
df1 %>%
   rowwise() %>%
   mutate(result = cur_data()[[type]]) %>%
   ungroup

-output

# A tibble: 2 × 7
  a         b c     d     e     type  result
  <lgl> <dbl> <lgl> <lgl> <lgl> <chr>  <dbl>
1 NA        1 NA    NA    NA    b          1
2 NA        2 NA    NA    NA    b          2

CodePudding user response:

This one could also be an option:

library(dplyr)
library(tibble)
df1 %>%
  mutate(across(everything(), as.character)) %>% 
  mutate(result=case_when(type=="a"~a,
                          type=="b"~b,
                          type=="c"~c,
                          type=="d"~d,
                          type=="e"~e,
                          TRUE~NA_character_)) %>% 
  type.convert(as.is = TRUE) %>% 
  as_tibble()
  a         b c     d     e     type  result
  <lgl> <int> <lgl> <lgl> <lgl> <chr>  <int>
1 NA        1 NA    NA    NA    b          1
2 NA        2 NA    NA    NA    b          2
  •  Tags:  
  • r
  • Related