我想从数据框中删除重复的行,仅适用于特定的列。可以通过以下方式获得distinct:
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
Run Code Online (Sandbox Code Playgroud)
这(几乎)是我所需要的。但是,我的问题是,我需要与之一起使用的列名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
Run Code Online (Sandbox Code Playgroud)
在eval似乎做一些有趣随着时代被过滤的数据量。(并且,添加了一个额外的列。不过,我可以忍受...)那么,如何获得相似的结果,就像我曾经使用过a,b,而是使用变量来代替呢?
我实际上gen通过读取数据框的列名获得了更多信息:gen <- colnames(data)[1:2]。通过@gymbrane提出的解决方案是完美的,如果我有办法改造gen来c(a, b)。关键是要避免对列名进行硬编码。我尝试了类似的操作gen <- noquotes(gen),该操作在rm_dup_rows下面建议的功能中没有给出错误,但确实给出了不同的结果,给出了与我开始时相同的重复过滤...
固定,
我想我可以使用了。这可能是unelegant,我不知道,如果每一步是必要的结果,但它通过组合@gymbrane提供以下功能似乎工作ensym,并quos同时添加到列表中的一个for循环中(编辑:GlobalEnv ISN不必要):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
Run Code Online (Sandbox Code Playgroud)
创建一个函数并使用quosures怎么样?也许这样的东西就是您正在寻找的......
rm_dup_rows <- function(data, ...){
vars = dplyr::quos(...)
data %>% distinct(!!! vars, .keep_all = T)
}
Run Code Online (Sandbox Code Playgroud)
我相信这会返回您所要求的
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
Run Code Online (Sandbox Code Playgroud)
您可以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
Run Code Online (Sandbox Code Playgroud)