【发布时间】:2021-07-19 11:32:55
【问题描述】:
我在dplyr::case_when() 中构建逻辑时遇到了一个奇怪的行为。
为什么逻辑 (col_a != col_b) | (col_a != col_c) 有效,而等效的 !col_a %in% c(col_b, col_c) 却无效,除非我们先 rowwise()?
示例
数据
df_colors <-
structure(
list(
col_a = c(
NA,
NA,
"blue",
"green",
"red",
"green",
"blue",
"red",
"green",
"red"
),
col_b = c(
NA,
NA,
"green",
"blue",
"blue",
"red",
NA,
"orange",
"orange",
"blue"
),
col_c = c(NA,
NA, NA, NA, NA, NA, "blue", NA, NA, NA)
),
row.names = c(NA,-10L),
class = c("tbl_df", "tbl", "data.frame")
)
df_colors
#> # A tibble: 10 x 3
#> col_a col_b col_c
#> <chr> <chr> <chr>
#> 1 <NA> <NA> <NA>
#> 2 <NA> <NA> <NA>
#> 3 blue green <NA>
#> 4 green blue <NA>
#> 5 red blue <NA>
#> 6 green red <NA>
#> 7 blue <NA> blue
#> 8 red orange <NA>
#> 9 green orange <NA>
#> 10 red blue <NA>
由reprex package (v2.0.0) 于 2021-07-19 创建
我的代码
两段等价的代码导致不同的输出。
library(dplyr)
desired_output <-
df_colors %>%
mutate(new_col = case_when(if_all(c(col_a, col_b, col_c), is.na) ~ NA_character_,
col_a == col_c ~ "col_a equals col_c",
col_a == col_b ~ "col_a equals col_b",
(col_a != col_b) | (col_a != col_c) ~ "col_a is neither col_b nor col_c" ))
strange_output <-
df_colors %>%
mutate(new_col = case_when(if_all(c(col_a, col_b, col_c), is.na) ~ NA_character_,
col_a == col_c ~ "col_a equals col_c",
col_a == col_b ~ "col_a equals col_b",
!col_a %in% c(col_b, col_c) ~ "col_a is neither col_b nor col_c" ))
desired_output
#> # A tibble: 10 x 4
#> col_a col_b col_c new_col
#> <chr> <chr> <chr> <chr>
#> 1 <NA> <NA> <NA> <NA>
#> 2 <NA> <NA> <NA> <NA>
#> 3 blue green <NA> col_a is neither col_b nor col_c
#> 4 green blue <NA> col_a is neither col_b nor col_c
#> 5 red blue <NA> col_a is neither col_b nor col_c
#> 6 green red <NA> col_a is neither col_b nor col_c
#> 7 blue <NA> blue col_a equals col_c
#> 8 red orange <NA> col_a is neither col_b nor col_c
#> 9 green orange <NA> col_a is neither col_b nor col_c
#> 10 red blue <NA> col_a is neither col_b nor col_c
strange_output
#> # A tibble: 10 x 4
#> col_a col_b col_c new_col
#> <chr> <chr> <chr> <chr>
#> 1 <NA> <NA> <NA> <NA>
#> 2 <NA> <NA> <NA> <NA>
#> 3 blue green <NA> <NA>
#> 4 green blue <NA> <NA>
#> 5 red blue <NA> <NA>
#> 6 green red <NA> <NA>
#> 7 blue <NA> blue col_a equals col_c
#> 8 red orange <NA> <NA>
#> 9 green orange <NA> <NA>
#> 10 red blue <NA> <NA
只有当我使用rowwise() 时,我才能通过第二个代码获得所需的输出。
desired_output_with_rowwise <-
df_colors %>%
rowwise() %>%
mutate(new_col = case_when(if_all(c(col_a, col_b, col_c), is.na) ~ NA_character_,
col_a == col_c ~ "col_a equals col_c",
col_a == col_b ~ "col_a equals col_b",
!col_a %in% c(col_b, col_c) ~ "col_a is neither col_b nor col_c" ))
除非我使用rowwise(),否则!col_a %in% c(col_b, col_c) 的结果为何与(col_a != col_b) | (col_a != col_c) 不同?
编辑
除了想了解为什么会有这种差异之外,这也是一个性能问题,因为使用rowwise() 会使操作在处理大数据时显着变慢。
【问题讨论】: