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

Why does dplyr::case_when break when trying to reference column name from setNames

这是我在 Whosebug 上的第一个问题。我正在尽最大努力创建下面的可重现示例,但请告诉我是否有不对的地方。我已经看到足够多的新手被活活烧死了,所以我希望这没问题。

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

我尝试使用 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
  )
  )

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

您需要将 names[[x]] 包裹在 sym() 中,然后使用 !! 对其求值。您可以通过 google 搜索 "Programming in 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 创建