取消引用字符串作为管道中的变量

我想删除数据框中的重复行,仅针对特定列.这可以通过以下方式获得:

data <- tibble(a = c(1, 1, 2, 2), b = c(3, 3, 3, 4), z = c(5,4,5,5))
filtered_data <- data %>% distinct(a, b, .keep_all = T)
dim(filtered_data)  
# [1] 3 3

这(几乎)是我需要的.然而,我的问题是我需要使用distinct的列名将改变.所以我有一个字符串gen包含我想用于distinct函数的列的名称.他们需要不加引号才能在管道中有用.我找到了使用as.name()或eval(parse())的建议.然而,这给了我一个不同的结果:

gen <- c("a", "b")
filtered_data <- data %>% distinct(eval(parse(text = gen)), .keep_all = T)
dim(filtered_data)  
# [1] 2 4

对于过滤数据的次数,eval似乎做了一些有趣的事情. (并且,添加了一个额外的列.我可以忍受这个,但是……)那么,如何获得类似的结果,就好像我使用了a,b,而是使用变量代替?

附加信息
我实际上通过读取数据帧的列名来获得gen:gen< – colnames(data)[1:2]. @gymbrane建议的解决方案是完美的,如果我有办法将gen转换为c(a,b).重点是避免对列名进行硬编码.我试过像gen< – noquotes(gen)这样的东西,它没有在下面建议的rm_dup_rows函数中给出错误,但它确实给出了不同的结果,给出了与我开始时相同的重复过滤… 固定
我想我搞定了.它可能是不优雅的,我不确定结果是否每一步都是必要的,但它似乎通过将下面的@gymbrane提供的函数与for循环中的ensym和quos相结合,同时添加到GlobalEnv中的列表(编辑) :GlobalEnv不是必需的):

unquote_string <- function(string) {
  out <- list()
  i <- 1
  for (s in string) {
    t <- ensym(s)
    out[i] <-dplyr::quos(!!t)
    i <- i+1
  }
return(out)
}
gen_quo <- unquote_string(gen)
filtered_data <- rm_dup_rows(data, gen_quo)
dim(filtered_data)
# [1] 3 3 

最佳答案 如何创建一个功能并使用
quosures.也许这样的事情就是你要找的……

rm_dup_rows <- function(data, ...){
  vars = dplyr::quos(...)
  data %>% distinct(!!! vars, .keep_all = T)
}

我相信这会回报你所要求的

rm_dup_rows(data = data, a, b)

# A tibble: 3 x 3
  a     b     z
<dbl> <dbl> <dbl>
    1     3     5
    2     3     5
    2     4     5


rm_dup_rows(data, b, z)
# A tibble: 3 x 3
a     b     z
<dbl> <dbl> <dbl>
    1     3     5
    1     3     4
    2     4     5

额外

您可以稍微修改rm_dup_rows并使用quos构造和向量.像这样……

rm_dup_rows <- function(data, vars){
  data %>% distinct(!!! vars, .keep_all = T)
}

# quos your column name vector
gen <- quos(a,z)

rm_dup_rows(data, gen)
# A tibble: 3 x 3
  a     b     z
 <dbl> <dbl> <dbl>
   1     3     5
   1     3     4
   2     3     5
点赞