【问题标题】:How to apply a function that takes data frame as input with purrr如何使用 purrr 应用将数据框作为输入的函数
【发布时间】:2020-03-05 07:59:33
【问题描述】:

有了这样的数据:

df <- tibble(x = runif(200), y = runif(200, 0, 3), is_active = sample(c(0, 1), size = 200, replace = TRUE, prob = c(0.2, 0.8)), 
             var1 = sample(c(0, 1), 200, TRUE), var2 = sample(c(0, 1), 200, TRUE))

# A tibble: 6 x 5
       x     y is_active  var1  var2
   <dbl> <dbl>     <dbl> <dbl> <dbl>
1 0.0812 2.42          0     0     0
2 0.313  1.61          0     1     1
3 0.241  2.90          1     0     0
4 0.906  1.08          1     0     1
5 0.652  2.86          0     0     0
6 0.231  0.730         1     1     0
...

我只想计算is_active 列的比例,只针对var1==1 的那些观察,然后是var2==1 等的那些。我编写了一个适用于一个变量的函数:

f <- function(df, var){
  var <- ensym(var)

  df %>%
    filter(!!var == 1) %>%
    mutate(xcut = cut(x, breaks = 10),
           ycut = cut(y, breaks = 20)) %>%
    group_by(xcut, ycut) %>%
    summarise(!!paste(var, 'proportion', sep = '_') := mean(is_active)) %>%
    ungroup()

}

如下调用它可以正常工作:

f(df, var1)
f(df, var2)

问题是我有数百个列,例如var1var2,我想遍历所有列,为每个列计算定义的is_active 比例。 map_at(df, vars(var1, var2), f) 在这里不起作用,因为它应用于后续列(向量),并且不会将整个数据帧作为每次调用的输入。我怎样才能实现它,最好使用purrr 包?

【问题讨论】:

    标签: r tidyverse purrr


    【解决方案1】:

    您可以将输入作为字符串传递给您的函数并稍微修改函数:

    library(tidyverse)
    
    f <- function(df, var){
    
       df %>%
        filter(!!sym(var) == 1) %>%
        mutate(xcut = cut(x, breaks = 10),
               ycut = cut(y, breaks = 20)) %>%
        group_by(xcut, ycut) %>%
        summarise(!!paste(var, 'proportion', sep = '_') := mean(is_active)) %>%
        ungroup()  
    }
    

    你可以这样做

    map(c('var1', 'var2'), f, df = df)
    
    #[[1]]
    # A tibble: 2 x 3
    #  xcut          ycut          var1_proportion
    #  <fct>         <fct>                   <dbl>
    #1 (0.231,0.239] (0.729,0.774]               1
    #2 (0.305,0.313] (1.57,1.61]                 0
    
    #[[2]]
    # A tibble: 2 x 3
    #  xcut          ycut        var2_proportion
    #  <fct>         <fct>                 <dbl>
    #1 (0.312,0.372] (1.58,1.61]               0
    #2 (0.847,0.907] (1.08,1.11]               1
    

    【讨论】:

    • 它有效,但我不太明白其中的区别。你能解释一下!!sym(var)var &lt;- ensym(var); !!var 有何不同吗?
    • @jakes sym 将引用的变量更改为符号。我还没有真正使用过ensym,但看起来ensym 适用于未引用的。
    【解决方案2】:

    我会做这样的事情

    calc_pct_isactive <- function(df, regex_col = "^var") {
        require(tidyverse)
    
        df %>% 
            pivot_longer(cols = matches(regex_col)) %>%
            group_by(is_active, name, value) %>%
            tally(name = "count") %>% 
            group_by(is_active, name) %>%
            mutate(base = sum(count,na.rm = TRUE),
                 pct = count/base) %>%
            filter(is_active ==1, value ==1)
    
    }
    calc_pct_isactive(df)
    

    【讨论】:

      猜你喜欢
      • 2021-06-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多