Another length error using dplyr mutate() and if_else()

Viewed 1088

I have another problem similar to by previous question here. As it is not exactly the same I have posted it as a new question.

I am attempting to add a vector as a new column to a tbl, but my vector is shorter than the number of rows, therefore I am using if_else() to specify a condition. Here is a reprex and my attempted solution:

library(dplyr)
library(magrittr)

data <- data.frame(
  ID = c("a100", "b100", "c100", "d100", "e100", "f100"),
  certainty = c("confirmed", "likely", "unsure", "likely", "unsure", "confirmed")
)

data %<>% as_tibble()

add <- c(1, 2)

data %<>%
  mutate(new_var =
           if_else(certainty == "likely", add, NA_real_))

This currently gives me the error Error: true must be length 6 (length of condition) or one, not 2, but as far as I can understand my condition is of length 2 since sum(data$certainty == "likely") returns [1] 2.

The result should look like this:

  ID    certainty new_var
  <fct> <fct>       <dbl>
1 a100  confirmed      NA
2 b100  likely          1
3 c100  unsure         NA
4 d100  likely          2
5 e100  unsure         NA
6 f100  confirmed      NA

What am I missing? Thanks again and sorry if this is a noob question, but I'm still trying to get to grips with the tidyverse!

2 Answers

Here is an option with replace

library(dplyr)
data %>%
   mutate(new_var = replace(rep(NA_real_, n()), certainty == "likely", add))
# A tibble: 6 x 3
#  ID    certainty new_var
#  <fct> <fct>       <dbl>
#1 a100  confirmed      NA
#2 b100  likely          1
#3 c100  unsure         NA
#4 d100  likely          2
#5 e100  unsure         NA
#6 f100  confirmed      NA

Here, the length of 'add' is known to be same as the number of 'likely' elements in 'certainty' and replace can do the replacement based on that info. In the case of if_else/ifelse/case_when, the arguments should have the same length as the condition vector. Here, 'add' have two elements and it is not 1 or the number of rows. If it is 1 element, then it can recycle


In data.table, we convert the 'data.frame' to 'data.table', specify the logical condition (certainty == "likely") in i, and assig (:=) the 'add' vector to create the column 'new_var'. By default, the non-matching elements will be filled with NA

library(data.table)
setDT(data)[certainty == "likely",  new_var := add]

This is one of those situations when using base R would be better than tidyverse or pipes.

data$new_var <- NA
data$new_var[data$certainty == 'likely'] <- add
data

#    ID certainty new_var
#1 a100 confirmed      NA
#2 b100    likely       1
#3 c100    unsure      NA
#4 d100    likely       2
#5 e100    unsure      NA
#6 f100 confirmed      NA
Related