【问题标题】:R: how to pass a list of filters to a functionR:如何将过滤器列表传递给函数
【发布时间】:2017-03-09 08:12:36
【问题描述】:

我有一个自定义过滤器列表,我需要根据这些过滤器对我的数据框进行子集化。例如,对于 mtcars,我有这个列表:

 filters=c(mpg>15, wt<2, carb>2 & am==0)

我想将此列表传递给包含 dplyr/pipes 的函数

fmean <- function(filter_x)   mtcars %>% filter(filter_x) %>% summarise(mean(disp))

将列表传递给 fmean 后我的预期输出是:

subset               mean(disp)
mpg>15                  192   
wt<2                    80.2
carb>2 & am==0          324

如何获得上述输出?

编辑:感谢@alistaire 和其他在这里回复的人,找到了一个 tidyverse 解决方案:

 library(tidyverse)
 filters <- c("mpg > 15", "wt < 2", "carb > 2 & am==0")

 fmean <- function(filter_x)   { mtcars %>%
                                   filter_(filter_x) %>%
                                   summarise(mean(disp)) %>% 
                                   mutate(subset=filter_x) %>%
                                   select(subset, everything()) }
 filters %>% map_df(fmean)

输出:

 subset               mean(disp)
 mpg>15                  192.3   
 wt<2                    80.2
 carb>2 & am==0          324.5

【问题讨论】:

    标签: r function filter dplyr


    【解决方案1】:

    实现这一点最直接的方法可能是使用purrr 包,它与dplyr 一起是tidyverse 包的一部分:

    library(tidyverse)
    
    filters <- c("mpg > 15", "wt < 2", "carb > 2 & am==0")
    
    fmean <- function(filter_x) {
      # Create list of means
      means <- filter_x %>% 
        map(~ mtcars %>% filter_(.dots = .x) %>% summarise(mean(disp)))
    
      # Create tibble from means
      tibble(subset = filter_x, means = unlist(means))
    }   
    
    fmean(filters)
    

    此外,您希望使用filter_ 而不是filter,这允许您将子集条件作为字符串而不是不带引号的文本传递。

    【讨论】:

    • 我很惊讶 tidyverse 的解决方案比使用 data.table 的单线更复杂
    • data.table 当然可以和最好的人一起打代码高尔夫:)
    • 为打高尔夫球而编辑 ^_^
    • 在看到@alistaire 对another question 的回答后,我在tidyverse 中看到了另一种方法。我将作为解决方案发布
    【解决方案2】:

    data.table方式,用eval(parse())

    library(data.table)
    mt_dt <- data.table(mtcars)
    
    filters <- c("mpg > 15", "wt < 2", "carb > 2 & am==0")
    
    out <- sapply(filters, function(x){mt_dt[eval(parse(text = x)), mean(disp)]})
    out
    # mpg > 15           wt < 2     carb > 2 & am==0 
    # 192.3115          80.2250             324.4600 
    

    我们正在遍历我们的过滤器,并且对于每个过滤器,我们子集并应用我们的聚合函数

    这会产生一个命名向量,使用起来非常灵活。如果你喜欢一张桌子,你可以使用:

    data.table(subset = names(out), `mean(disp)` = out)
    #              subset mean(disp)
    # 1:         mpg > 15   192.3115
    # 2:           wt < 2    80.2250
    # 3: carb > 2 & am==0   324.4600
    

    【讨论】:

    • 不应该转置得到想要的输出吗?
    • @Irakli 我可能更喜欢使用命名向量,但经过编辑以将转换包含到表格中。
    【解决方案3】:

    在基础 R 中:

    fmean <- function(filter_x)  data.frame(
      subset=filter_x, 
      do.call(rbind,
              lapply(filter_x, function(x) 
                mtcars %>% filter_(x) %>% summarise(mean(disp)))))
    
    fmean(filters)
                subset mean.disp.
    1         mpg > 15   192.3115
    2           wt < 2    80.2250
    3 carb > 2 & am==0   324.4600
    

    【讨论】:

      猜你喜欢
      • 2011-09-23
      • 1970-01-01
      • 2017-09-14
      • 1970-01-01
      • 2023-01-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-14
      相关资源
      最近更新 更多