【问题标题】:Using dplyr filter() in programming在编程中使用 dplyr filter()
【发布时间】:2017-12-26 22:11:09
【问题描述】:

我正在编写我的函数并想使用 dplyr 的 filter() 函数来选择满足条件的数据帧行。这是我的代码:

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 没有选择任何满足条件的行。

我怎样才能做到这一点?

更新

由于某种原因,这在我不使用 `%in%, as 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%

【问题讨论】:

  • 看看filter_
  • @HubertL,是的,我知道,而且 filter_ 正在逐步淘汰
  • 你在哪里读到这个?
  • @HubertL 在 dplyr 手册页中。执行?filter_,您会看到它已被弃用。
  • 不是真的……只是我的一个想法。由于这些功能是不推荐使用的版本,它们很可能很快就会被淘汰。我不想使用它们。

标签: r dplyr tidyverse rlang


【解决方案1】:

我遇到了类似的问题,对我有用的简单解决方法是在“过滤器”动词中使用“.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()

希望有人对此有所帮助。

【讨论】:

    【解决方案2】:

    现在不推荐使用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
    

    【讨论】:

      【解决方案3】:

      我同意@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)))
      

      【讨论】:

      • 我想提一下 UQ 现在已弃用。请查看使用 dplyr 进行现代编程的双胡子运算符。我建议观看 Lionel Henry 最近的任何演讲。
      【解决方案4】:

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

      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))
      

      尽管有大量使用df 的“官方”“tidyverse”示例,但它是stats pkg 中的一个函数,我尽量避免再使用它。

      既然你用的是tidyverse,不妨利用map_df() from purrr

      【讨论】:

      • 我不明白“大量使用df 的“官方”“tidyverse”示例,这是stats pkg 中的一个函数。我没有看到任何 stats 函数。我猜你的意思是base::lapply
      • @dpprdan df 返回 F 分布的密度,来自 stats 包。我同意@hrbrmstr,我也停止使用df 进行命名
      • 如果将rlang::sym() 替换为基本函数as.name(),则无需加载library(rlang) 即可逃脱
      • 这个答案将不再有效,因为 UQE 现在已弃用。请检查我的答案或其他。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-13
      • 2016-03-17
      • 1970-01-01
      • 2017-12-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多