尝试从setNames引用列名称时,为什么dplyr :: case_when中断

时间:2019-07-12 16:33:34

标签: r dplyr case-when

这是我关于StackOverflow的第一个问题。我正在尽力在下面创建可复制的示例,但是请告诉我是否有不正确的地方。我已经看到足够多的新手被烧死,所以我希望这可以。

我正在尝试编写一个函数,该函数将使用dplyr :: case_when从包含TRUE-FALSE值的行中返回单个值。如果我对列名进行硬编码,那么一切工作都会很漂亮,但是每当我尝试从其他地方引用该名称时,它就会以字符串形式返回,因此会中断。我已经为此工作了几个小时,所以我一定会错过一些简单的东西。

我尝试使用assign,get和eval(parse))失败。还尝试通过列表,但没有成功。

xcol1 <- c(TRUE, FALSE, FALSE, FALSE, FALSE)
xcol2 <- c(FALSE, TRUE, FALSE, FALSE, FALSE)
xcol3 <- c(FALSE, FALSE, TRUE, FALSE, FALSE)
xcol4 <- c(FALSE, FALSE, FALSE, TRUE, FALSE)
xcol5 <- c(FALSE, FALSE, FALSE, FALSE, TRUE)
ycol1 <- c(TRUE, FALSE, FALSE, FALSE, FALSE)
ycol2 <- c(FALSE, TRUE, FALSE, FALSE, FALSE)
ycol3 <- c(FALSE, FALSE, TRUE, FALSE, FALSE)
ycol4 <- c(FALSE, FALSE, FALSE, TRUE, FALSE)
ycol5 <- c(FALSE, FALSE, FALSE, FALSE, TRUE)

data <- data.frame(xcol1, xcol2, xcol3, xcol4, xcol5, ycol1, ycol2, ycol3, ycol4, ycol5)

colSelect <- "xcol"

names <- setNames(paste0(colSelect, seq(1, 7)), seq(1, 7))

#Works when column names are hard coded
cols <- select(data, contains(colSelect)) %>%
  mutate(bad_good = case_when(
    xcol1 == TRUE ~ 1,
    xcol2 == TRUE ~ 2,
    xcol3 == TRUE ~ 3,
    xcol4 == TRUE ~ 4,
    xcol5 == TRUE ~ 5
  )
  )

#Doesn't work when column names are referenced from a subset 
cols2 <- select(data, contains(colSelect)) %>%
  mutate(bad_good = case_when(
    names[[1]] == TRUE ~ 1,
    names[[2]] == TRUE ~ 2,
    names[[3]] == TRUE ~ 3,
    names[[4]] == TRUE ~ 4,
    names[[5]] == TRUE ~ 5
  )
  )

从多列TRUE-FALSE值中输出单个列时,我需要能够使用case_when,并且这些列的名称可以从colSelect变量中自定义。

1 个答案:

答案 0 :(得分:0)

您需要将names[[x]]包装在sym()中,然后使用!!对其进行评估。您可以通过Google搜索“在Dplyr中编程”

了解更多信息
library(tidyverse)

colSelect1 <- "xcol"

names1 <- setNames(paste0(colSelect1, seq(1, 7)), seq(1, 7))

cols1 <- select(data, contains(colSelect1)) %>%
    mutate_all(as.logical) %>% 
    mutate(bad_good = case_when(
        !!sym(names1[[1]]) ~ 1,
        !!sym(names1[[2]])  ~ 2,
        !!sym(names1[[3]])  ~ 3,
        !!sym(names1[[4]]) ~ 4,
        !!sym(names1[[5]]) ~ 5,
    )
    )

cols1
#>   xcol1 xcol2 xcol3 xcol4 xcol5 bad_good
#> 1  TRUE FALSE FALSE FALSE FALSE        1
#> 2 FALSE  TRUE FALSE FALSE FALSE        2
#> 3 FALSE FALSE  TRUE FALSE FALSE        3
#> 4 FALSE FALSE FALSE  TRUE FALSE        4
#> 5 FALSE FALSE FALSE FALSE  TRUE        5

colSelect2 <- "ycol"

names2 <- setNames(paste0(colSelect2, seq(1, 7)), seq(1, 7))

cols2 <- select(data, contains(colSelect2)) %>%
    mutate_all(as.logical) %>% 
    mutate(bad_good = case_when(
        !!sym(names2[[1]]) ~ 1,
        !!sym(names2[[2]])  ~ 2,
        !!sym(names2[[3]])  ~ 3,
        !!sym(names2[[4]]) ~ 4,
        !!sym(names2[[5]]) ~ 5,
    )
    )

cols2
#>   ycol1 ycol2 ycol3 ycol4 ycol5 bad_good
#> 1  TRUE FALSE FALSE FALSE FALSE        1
#> 2 FALSE  TRUE FALSE FALSE FALSE        2
#> 3 FALSE FALSE  TRUE FALSE FALSE        3
#> 4 FALSE FALSE FALSE  TRUE FALSE        4
#> 5 FALSE FALSE FALSE FALSE  TRUE        5

reprex package(v0.3.0)于2019-07-12创建