返回小标题:如何使用 case_when 进行矢量化?

Dav*_*d T 6 r unnest dplyr tibble

我有一个返回小标题的函数。它运行正常,但我想对其进行矢量化。

library(tidyverse)

tibTest <- tibble(argX = 1:4, argY = 7:4)

square_it <- function(xx, yy) {
  if(xx >= 4){
    tibble(x = NA, y = NA)
  } else if(xx == 3){
    tibble(x = as.integer(), y = as.integer())
  } else if (xx == 2){
    tibble(x = xx^2 - 1, y = yy^2 -1)
  } else {
    tibble(x = xx^2, y = yy^2)
  }
}
Run Code Online (Sandbox Code Playgroud)

mutate当我用 调用它时map2,它运行正常,给了我想要的结果:

tibTest %>%
  mutate(sq = map2(argX, argY, square_it)) %>%
  unnest()
## A tibble: 3 x 4
#     argX  argY     x     y
#    <int> <int> <dbl> <dbl>
# 1     1     7     1    49
# 2     2     6     3    35
# 3     4     4    NA    NA
Run Code Online (Sandbox Code Playgroud)

我第一次尝试对它进行矢量化失败了,我明白为什么 - 我无法返回小标题的矢量。

square_it2 <- function(xx, yy){
  case_when(
    x >= 4 ~ tibble(x = NA, y = NA),
    x == 3 ~ tibble(x = as.integer(), y = as.integer()),
    x == 2 ~ tibble(x = xx^2 - 1, y = yy^2 -1),
    TRUE   ~ tibble(x = xx^2,     y = yy^2)
  )
}
# square_it2(4, 2)  # FAILS
Run Code Online (Sandbox Code Playgroud)

我的下一次尝试在一个简单的输入上运行正常。我可以返回一个 tibbles 列表,这就是我想要的unnest

square_it3 <- function(xx, yy){
  case_when(
    xx >= 4 ~ list(tibble(x = NA, y = NA)),
    xx == 3 ~ list(tibble(x = as.integer(), y = as.integer())),
    xx == 2 ~ list(tibble(x = xx^2 - 1, y = yy^2 -1)),
    TRUE   ~ list(tibble(x = xx^2,     y = yy^2))
  )
}
square_it3(4, 2)
# [[1]]
# # A tibble: 1 x 2
# x     y    
# <lgl> <lgl>
#   1 NA    NA   
Run Code Online (Sandbox Code Playgroud)

但是当我在 a 中调用它时mutate,它并没有给我与square_it. 我可以看出哪里出了问题。在xx == 2子句中,xx充当 2 的原子值。但在构建 tibble 时,xx是一个长度为 4 的向量。

tibTest %>%
  mutate(sq =  square_it3(argX, argY)) %>%
  unnest()
# # A tibble: 9 x 4
#    argX  argY     x     y
#    <int> <int> <dbl> <dbl>
# 1     1     7     1    49
# 2     1     7     4    36
# 3     1     7     9    25
# 4     1     7    16    16
# 5     2     6     0    48
# 6     2     6     3    35
# 7     2     6     8    24
# 8     2     6    15    15
# 9     4     4    NA    NA
Run Code Online (Sandbox Code Playgroud)

如何获得与使用 相同的结果square_it,但从使用 的矢量化函数获得case_when

All*_*ron 2

您需要确保每次调用该函数时都创建 1 行 tibble,然后对其进行矢量化。

无论您是否有rowwise团体,这都有效。

您可以通过switch包裹来做到这一点map2

这是一个代表:

library(tidyverse)

tibTest <- tibble(argX = 1:4, argY = 7:4)

square_it <- function(xx, yy) {
  map2(xx, yy, function(x, y){
    switch(which(c(x >= 4, 
                   x == 3, 
                   x == 2, 
                   x < 4 & x != 3 & x != 2)),
           tibble(x = NA, y = NA),
           tibble(x = as.integer(), y = as.integer()),
           tibble(x = x^2 - 1, y = y^2 -1),
           tibble(x = x^2, y = y^2))})
}

tibTest %>% mutate(sq =  square_it(argX, argY)) %>% unnest(cols = sq)
#> # A tibble: 3 x 4
#>    argX  argY     x     y
#>   <int> <int> <dbl> <dbl>
#> 1     1     7     1    49
#> 2     2     6     3    35
#> 3     4     4    NA    NA
Run Code Online (Sandbox Code Playgroud)

reprex 包(v0.3.0)于 2020-05-16 创建