在编程中使用 dplyr filter()

Using dplyr filter() in programming

我正在编写我的函数,并希望将 dplyr 的 filter() 函数用于 select 满足条件的数据框行。这是我的代码:

library(tidyverse)

df <-data.frame(x = sample(1:100, 50), y = rnorm(50), z = sample(1:100,50), w = sample(1:100, 50),
            p = sample(1:100,50))

new <- function(ang,brad,drau){
  df%>%filter(!!drau %in% 1:50)%>%select(ang,brad) -> A
return(A)
}

brand <- c("z","w","p")
lapply(1:3, function(i) new(ang = "x", brad = "y", drau = brand[i]))%>%bind_rows()

任何时候我 运行 这个函数,看起来 filter 没有 select 任何满足条件的行。

我怎样才能完成这项工作?

更新

出于某种原因,这在我不使用 `%in% 时有效,例如;

new <- function(ang,brad,drau){
  df%>%filter(!!drau > 50)%>%select(ang,brad) -> A
return(A)
}

lapply(1:3, function(i) new(ang = "x", brad = "y", drau = brand[i]))%>%bind_rows()

但是,每个循环的结果都是相同的。为什么会这样?还有为什么我不能使用 %in%

这似乎符合您的要求(但需要您确认):

library(tidyverse)
library(rlang)

set.seed(1492)

xdf <- data_frame(
  x = sample(1:100, 50),
  y = rnorm(50), 
  z = sample(1:100,50), 
  w = sample(1:100, 50),
  p = sample(1:100,50)
)

new_df <- function(ang, brad, drau) {
  drau <- sym(drau)
  filter(xdf, UQE(drau) %in% 1:50) %>% 
    select(ang, brad)
}

brand <- c("z", "w", "p")

map_df(brand, ~new_df(ang = "x", brad = "y", drau = .x))

尽管有大量 "official" "tidyverse" 示例使用 df,它是 stats pkg 中的一个函数,我尽量避免再使用它。

由于您使用的是 tidyverse,不妨利用 purrr 中的 map_df()

我同意@hrbrmstr 的标准评估方案。正如@hadley today 建议的那样,这里是 NSE 解决方案:

library(tidyverse)

df <-data.frame(x = sample(1:100, 50), 
                y = rnorm(50), 
                z = sample(1:100,50), 
                w = sample(1:100, 50),
                p = sample(1:100,50))

new <- function(ang, brad, drau){
  ang  <- enquo(ang)
  brad <- enquo(brad)
  drau <- enquo(drau)

  df %>% filter(UQ(drau) %in% 1:50) %>%
    select(UQ(ang),UQ(brad)) 
}

brand <- c("z","w","p")
brand <- rlang::syms(brand)

map_df(brand, ~new(ang = x, brad = y, drau = UQ(.x)))

随着 UQE 现已弃用,此问题的已接受答案将无效。这个答案应该有效。这里唯一的变化是 !!sym()

library(rlang)
library(tidyverse)

df <-data.frame(x = sample(1:100, 50), y = rnorm(50), z = sample(1:100,50), w = sample(1:100, 50),
                p = sample(1:100,50))

new <- function(ang,brad,drau){
  df%>%filter(!!sym(drau) %in% 1:50)%>%select(!!sym(ang), !!sym(brad)) -> A
  return(A)
}

brand <- c("z","w","p")
lapply(1:3, function(i) new(ang = "x", brad = "y", drau = brand[i]))%>%bind_rows()

如果您不想将函数参数作为字符串传递,请改用 !!enquo()

new <- function(ang,brad,drau){
  df%>%filter(!!enquo(drau) %in% 1:50)%>%select(!!enquo(ang), !!enquo(brad)) -> A
  return(A)
}

> head(new(ang = x, brad = y, drau = z))
    x           y
1  44  0.47702540
2  84 -1.09670409
3  59 -0.20556334
4  81 -0.46306635
5  93  1.36845485
6   8  0.37392587

我遇到了类似的问题,对我有用的简单解决方法是在“过滤器”动词中使用“.data”代词,特别是在这种情况下:

filter(.data[[drau]] %in% 1:50)

更多信息在这里:https://tinyheero.github.io/2020/03/01/use-data-env-pronouns-tidyverse.html Lionel Henry 最近在 Rstudio 的 youtube 频道上的演讲也很有帮助。

library(tidyverse)

df <-data.frame(x = sample(1:100, 50), y = rnorm(50), z = sample(1:100,50), w = sample(1:100, 50),
                p = sample(1:100,50))

new <- function(ang,brad,drau){
  df%>%filter(.data[[drau]] %in% 1:50)%>%select(ang,brad) -> A
  return(A)
}

brand <- c("z","w","p")
lapply(1:3, function(i) new(ang = "x", brad = "y", drau = brand[i]))%>%bind_rows()

希望有人能从中找到一些用处。