在dplyr中使用filter_,其中字段和值都在变量中

Ric*_*cky 12 r dplyr

我想使用在变量中定义的字段来过滤数据帧,以选择也在变量中的值.说我有

df <- data.frame(V=c(6, 1, 5, 3, 2), Unhappy=c("N", "Y", "Y", "Y", "N"))
fld <- "Unhappy"
sval <- "Y"
Run Code Online (Sandbox Code Playgroud)

我想要的价值是df[df$Unhappy == "Y", ].

我已经阅读了nse小插图试图使用,filter_但不太明白.我试过了

df %>% filter_(.dots = ~ fld == sval)
Run Code Online (Sandbox Code Playgroud)

什么也没有回来.我得到了我想要的东西

df %>% filter_(.dots = ~ Unhappy == sval)
Run Code Online (Sandbox Code Playgroud)

但显然这违背了使用变量来存储字段名称的目的.请问有什么线索吗?最终我想使用它在哪里fld是字段名称sval的向量,并且是每个字段的过滤器值的向量fld.

akr*_*run 15

您可以尝试interplazyeval

 library(lazyeval)
 library(dplyr)
 df %>%
     filter_(interp(~v==sval, v=as.name(fld)))
 #   V Unhappy
 #1 1       Y
 #2 5       Y
 #3 3       Y
Run Code Online (Sandbox Code Playgroud)

对于多个键/值对,我发现这是有效的,但我认为应该有更好的方法.

  df1 %>% 
    filter_(interp(~v==sval1[1] & y ==sval1[2], 
           .values=list(v=as.name(fld1[1]), y= as.name(fld1[2]))))
 #  V Unhappy Col2
 #1 1       Y    B
 #2 5       Y    B
Run Code Online (Sandbox Code Playgroud)

对于这些情况,我发现base R选项更容易.例如,如果我们filter根据'fld1'中的'key'变量尝试使用'sval1'中相应值的行,则使用一个选项Map.我们对数据集(df1[fld1])进行子集化,并将FUN(==)应用于df1[f1d1]'sval1' 中具有相应值的每一列,并使用&with Reduce获取可用于filter'df1'行的逻辑向量.

 df1[Reduce(`&`, Map(`==`, df1[fld1],sval1)),]
 #   V Unhappy Col2
 # 2 1       Y    B
  #3 5       Y    B
Run Code Online (Sandbox Code Playgroud)

数据

df1 <- cbind(df, Col2= c("A", "B", "B", "C", "A"))
fld1 <- c(fld, 'Col2')
sval1 <- c(sval, 'B')    
Run Code Online (Sandbox Code Playgroud)


LmW*_*mW. 9

使用dplyr 0.5.0及更高版本,可以使用更简单的语法并更接近@Ricky最初想要的语法,我发现它比使用更具可读性 rlang

packageVersion("rlang")
# [1] ‘0.4.0’

df <- data.frame(V=c(6, 1, 5, 3, 2), Unhappy=c("N", "Y", "Y", "Y", "N"))
fld <- "Unhappy"
sval <- "Y"

df %>% filter(.data[[fld]]==sval)

#OR
filter_col_val <- function(df, fld, sval) {
  df %>% filter({{fld}}==sval)
}

filter_col_val(df, Unhappy, "Y")
Run Code Online (Sandbox Code Playgroud)

更新: 使用dplyr 0.6.0及更高版本,此代码有效:

packageVersion("dplyr")
# [1] ‘0.7.1’

df <- data.frame(V=c(6, 1, 5, 3, 2), Unhappy=c("N", "Y", "Y", "Y", "N"))
fld <- "Unhappy"
sval <- "Y"

df %>% filter(UQ(rlang::sym(fld))==sval)

#OR
df %>% filter((!!rlang::sym(fld))==sval)

#OR
fld <- quo(Unhappy)
sval <- "Y"
df %>% filter(UQ(fld)==sval)
Run Code Online (Sandbox Code Playgroud)

有关http://dplyr.tidyverse.org/articles/programming.html上dplyr提供的语法以及包https://cran.r-project.org/web/packages/rlang/index.html中的quosure用法的更多信息.rlang

更新更新:如果您发现在dplyr 0.6+中掌握非标准评估的挑战性,Alex Hayes就该主题撰写了一篇精彩的文章:https://alexpghayes.github.io/2017/gentle-non-standard-evaluation -in-dplyr-0-6 /


RHe*_*tel 8

这是基础的替代方案,R可能不是很优雅,但它可能具有易于理解的好处:

df[df[colnames(df)==fld]==sval,]
#  V Unhappy
#2 1       Y
#3 5       Y
#4 3       Y
Run Code Online (Sandbox Code Playgroud)