r - dplyr 使用 case_when 改变新的动态变量

标签 r dynamic dplyr

我知道类似的问题 herehere ,但我一直无法找出适合我的具体情况的正确解决方案。我发现的一些解决方案是使用 mutate_等,但我知道这些现在已经过时了。我是 dplyr 动态用法的新手。

我有一个数据框,其中包含一些带有两个不同前缀 alpha 和 beta 的变量:

df <- data.frame(alpha.num = c(1, 3, 5, 7),
             alpha.char = c("a", "c", "e", "g"),
             beta.num = c(2, 4, 6, 8),
             beta.char = c("b", "d", "f", "h"),
             which.to.use = c("alpha", "alpha", "beta", "beta"))

我想创建前缀为“chosen”的新变量。它们是“alpha”或“beta”列的副本,具体取决于“which.to.use”列中该行的名称。所需的输出是:
desired.df <- data.frame(alpha.num = c(1, 3, 5, 7),
                     alpha.char = c("a", "c", "e", "g"),
                     beta.num = c(2, 4, 6, 8),
                     beta.char = c("b", "d", "f", "h"),
                     which.to.use = c("alpha", "alpha", "beta", "beta"),
                     chosen.num = c(1, 3, 6, 8),
                     chosen.char = c("a", "c", "f", "h"))

我失败的尝试:
varnames <- c("num", "char")
df %<>%
  mutate(as.name(paste0("chosen.", varnames)) := case_when(
    which.to.use == "alpha" ~ paste0("alpha.", varnames),
    which.to.use == "beta" ~ pasteo("beta.", varnames)
  ))

我更喜欢纯 dplyr 解决方案,甚至更好的是可以包含在修改 df 的更长管道中的解决方案(即无需停下来创建“varnames”)。谢谢你的帮助。

最佳答案

使用一些乐趣 rlang东西 & purrr :

library(rlang)
library(purrr)
library(dplyr)

df <- data.frame(alpha.num = c(1, 3, 5, 7),
                 alpha.char = c("a", "c", "e", "g"),
                 beta.num = c(2, 4, 6, 8),
                 beta.char = c("b", "d", "f", "h"),
                 which.to.use = c("alpha", "alpha", "beta", "beta"),
                 stringsAsFactors = F)

c("num", "char") %>% 
    map(~ mutate(df, !!sym(paste0("chosen.", .x)) := 
      case_when(
          which.to.use == "alpha" ~ !!sym(paste0("alpha.", .x)),
          which.to.use == "beta" ~ !!sym(paste0("beta.", .x))
                ))) %>% 
    reduce(full_join)

结果:
  alpha.num alpha.char beta.num beta.char which.to.use chosen.num chosen.char
1         1          a        2         b        alpha          1           a
2         3          c        4         d        alpha          3           c
3         5          e        6         f         beta          6           f
4         7          g        8         h         beta          8           h

reduce(full_join) :
c("num", "char") %>% 
  map_dfc(~ mutate(df, !!sym(paste0("chosen.", .x)) := 
                 case_when(
                   which.to.use == "alpha" ~ !!sym(paste0("alpha.", .x)),
                   which.to.use == "beta" ~ !!sym(paste0("beta.", .x))
                 ))) %>% 
  select(-ends_with("1"))



alpha.num alpha.char beta.num beta.char which.to.use chosen.num chosen.char
1         1          a        2         b        alpha          1           a
2         3          c        4         d        alpha          3           c
3         5          e        6         f         beta          6           f
4         7          g        8         h         beta          8           h

解释:
(注意:我没有完全或什至没有得到 rlang 。也许其他人可以给出更好的解释;)。

使用 paste0当我们需要 mutate 的裸名时,它本身会产生一个字符串。知道它指的是一个变量名。

如果我们包装 paste0sym ,它的计算结果是一个裸名:
> x <- varrnames[1]
> sym(paste0("alpha.", x))
  alpha.num

但是mutate不知道评估,而是将其视为符号:
> typeof(sym(paste0("alpha.", x)))
[1] "symbol"

“砰砰”声!!运算符计算 sym功能。相比:
> expr(mutate(df, var = sym(paste0("alpha.", x))))
mutate(df, var = sym(paste0("alpha.", x)))

> expr(mutate(df, var = !!sym(paste0("alpha.", x))))
mutate(df, var = alpha.num)

所以与 !!sym我们可以使用 paste 来动态调用带有 dplyr 的变量名。

关于r - dplyr 使用 case_when 改变新的动态变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51644516/

相关文章:

r - 基于现有列创建多个新列 (dplyr)

r - 百分比标签到 100% 堆栈图尝试 "mutate"但不起作用

r - 在 R 中获取 Biostrings 对象的长 DNA 序列的完整 View

regex - 在定界符的第一个/第n个出现时进行拆分

用于动态创建的 html 页面的 php 或 jquery?

r 用填充的数据扩展数据集

r - 如何删除带有 NA 的元素

c# - 动态Where Linq 到实体

c# - 从现有列表构建动态 linq 选择查询

r - 如何仅将函数应用于 dplyr 中组的第一行?