首页 > 解决方案 > 无法识别地图函数内的对象(另一种情况)

问题描述

这个问题实际上和我之前的问题几乎是重复的(An object inside map function is not识别),但是由于我遇到了类似的问题,所以我想对这个现象有一个准确的了解。

假设我有以下数据框,

df <- structure(list(a11 = c(TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE),
                     a12 = c(FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, TRUE),
                     a21 = c(TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE),
                     a22 = c(FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE), 
                     b11 = c(TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE),
                     b12 = c(TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE),
                     b21 = c(TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE),
                     b22 = c(TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE)),
                row.names = c(NA, -10L), class = c("tbl_df", "tbl", "data.frame"))

并尝试根据现有列的组合(例如a11b11)添加四个新列。

(预期输出)

structure(list(Group11 = c("g1", "g1", "g3", "g3", "g2", "g2", "g1", "g3", "g2", "g3"),
               Group12 = c("g3", "g1", "g4", "g2", "g3", "g1", "g4", "g3", "g1", "g1"),
               Group21 = c("g1", "g2", "g1", "g2", "g3", "g2", "g1", "g3", "g4", "g2"),
               Group22 = c("g3", "g2", "g2", "g1", "g3", "g3", "g4", "g3", "g3", "g3")),
          row.names = c(NA, -10L), class = c("tbl_df", "tbl", "data.frame"))

我首先尝试了这段代码:

1:2 %>% expand_grid(i1=., i2=.) %>% mutate(data=map2(i1, i2, function(i1, i2){
  df %>% transmute(
    !!(str_c("Group", i1, i2)):=if_else(!!sym(str_c("a", i1, i2)),
                                        if_else(!!sym(str_c("b", i1, i2)), "g1", "g2"),
                                        if_else(!!sym(str_c("b", i1, i2)), "g3", "g4"))) %>% return()
})) %>% .$data %>% reduce(bind_cols)

并得到一个错误,上面写着:Error: object 'i1' not found

但是,如果我尝试如下另一个代码,

fun_group <- function(i1, i2){
  df %>% transmute(
    !!(str_c("Group", i1, i2)):=if_else(!!sym(str_c("a", i1, i2)),
                                        if_else(!!sym(str_c("b", i1, i2)), "g1", "g2"),
                                        if_else(!!sym(str_c("b", i1, i2)), "g3", "g4"))) %>% return()
}
1:2 %>% expand_grid(i1=., i2=.) %>% mutate(data=map2(i1, i2, fun_group)) %>% .$data %>% reduce(bind_cols)

然后我成功地得到了预期的输出。

两者的区别在于我只是在我的第二个代码中声明了我原来的函数fun_groupmap函数,但结果完全不同,我很难理解是什么导致了这种差异。

map如果您能告诉我导致这些不同结果的确切功能机制,我将不胜感激。
很抱歉两次发布类似问题,非常感谢您提前提供的帮助!

标签: rpurrr

解决方案


使用pmap. 它会自动生成 data.frame 的第一列.x和第二列.y

library(tidyverse)
1:2 %>%
  expand_grid(i1=., i2=.) %>%
  pmap_chr(~str_c(.x,.y)) %>%
  setNames(str_c("Group",.)) %>%
  map_dfc(~ df %>% 
            select(ends_with(.x)) %>%
            pmap_chr(~case_when(.x & .y ~ "g1",
                                .x & !.y ~ "g2",
                                !.x & .y ~ "g3",
                                !.x & !.y ~ "g4",
                                TRUE ~ NA_character_)))
# A tibble: 10 x 4
   Group11 Group12 Group21 Group22
   <chr>   <chr>   <chr>   <chr>  
 1 g1      g3      g1      g3     
 2 g1      g1      g2      g2     
 3 g3      g4      g1      g2     
 4 g3      g2      g2      g1     
 5 g2      g3      g3      g3     
 6 g2      g1      g2      g3     
 7 g1      g4      g1      g4     
 8 g3      g3      g3      g3     
 9 g2      g1      g4      g3     
10 g3      g1      g2      g3     

推荐阅读