Почему case_when не может возвращать векторы разной длины? - PullRequest
0 голосов
/ 25 мая 2020

Это не удается:

library(tidyverse)
myFn <- function(nmbr){
  case_when(
    nmbr > 3 ~ letters[1:3],
    TRUE ~ letters[1:2]
  )
}

myFn(4)
# Error: `TRUE ~ letters[1:2]` must be length 3 or one, not 2
# Run `rlang::last_error()` to see where the error occurred.

Почему не удается? Почему case_when построен таким образом, что его ветви не могут возвращать векторы разной длины? Я бы хотел, чтобы myFn работал, чтобы я мог делать что-то вроде:

tibble(fruit = c("apple", "grape"),
       count = 3:4) %>% 
  mutate(bowl = myFn(count)) %>% 
  unnest(col = "bowl")

и получать

# A tibble: 5 x 3
fruit count  bowl
<chr> <int> <int>
1 apple     3     a
2 apple     3     b
3 grape     4     a
4 grape     4     b
5 grape     4     c

Я могу заставить его работать - написав не векторизованный myFn используя if/else, а затем оборачивая его в map, но зачем мне это нужно?

1 Ответ

1 голос
/ 25 мая 2020

Согласно моим комментариям, ваша функция должна возвращать один элемент для каждой строки ввода. Однако каждый из этих элементов может быть list длины 0 или более (и произвольной сложности). Попробуйте это:

myFn <- function(nmbr){
  case_when(
    nmbr > 3 ~ list(letters[1:3]),
    TRUE ~ list(letters[1:2])
  )
}
tibble(fruit = c("apple", "grape"),
       count = 3:4) %>%
  mutate(bowl = myFn(count))
# # A tibble: 2 x 3
#   fruit count bowl     
#   <chr> <int> <list>   
# 1 apple     3 <chr [2]>
# 2 grape     4 <chr [3]>
tibble(fruit = c("apple", "grape"),
       count = 3:4) %>%
  mutate(bowl = myFn(count)) %>%
  unnest(col = "bowl")
# # A tibble: 5 x 3
#   fruit count bowl 
#   <chr> <int> <chr>
# 1 apple     3 a    
# 2 apple     3 b    
# 3 grape     4 a    
# 4 grape     4 b    
# 5 grape     4 c    
...