为什么 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 创建
这是我在 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 创建