将dplyr函数应用于值列表的过程是什么

时间:2019-04-23 22:39:48

标签: r dplyr

我创建了一个dplyr函数来评估总体事件计数。与dplyr :: filter和dplyr :: group_by函数中的变量的显式命名一起使用时,该代码有效。

我需要将该函数应用于24个变量,这些变量是数据帧内的列标题。在这里,它们被称为x。

我用过!据我了解,该变量被评估为字符串而不是列名。

功能

summary_table <- function(x){
  assign(paste(x,"sum_tab", sep="_"),
         envir = parent.frame(),
         value = df %>%
  filter(!is.na(!!x)) %>%
  group_by(!!x) %>%
  summarise(
           'Variable name' = paste0(x),
            Discharged = sum(admission_status == "Discharged"),
           'Re-attended' = sum(!is.na(re_admission_status)),
           'Admitted on Re-attendance' = sum(re_admission_status == "Admitted", na.rm = TRUE)))
}


我用过:

sapply(var_names, summary_table)

但是对于列表var_names中的每个变量,它仅输出表的一行

总而言之,我希望有指向正确机制的指针,以将上面编写的函数应用于dplyr管道内的列名列表。

可复制的示例

example <- mtcars %>%
  group_by(vs) %>%
  summarise(
    '6 cylinder' = sum(cyl == 6),
    'Large disp' = sum(disp >= 100),
    'low gears' = sum(gear <= 4))
})

在此示例中,我们希望将此功能应用于以下列表

cars_var <- c("vm", "am", "carb")

这将为列表中的每一列生成三个表。

1 个答案:

答案 0 :(得分:2)

正如@ eipi10所说,自动创建变量通常是不明智的。一个更好的主意是创建一个单独的变量,该变量是数据帧的列表。

让用户使用group_by()group_by_at()自己应用组也更容易,这样您就不必担心他们如何提供变量名称。

编辑2019-05-2

一种方法是将分组变量的名称视为“数据”,并映射它们,以创建由每个分组变量分组的实际数据的副本。

library(dplyr)
library(purrr)

grouping_vars <- c("vs", "am", "carb")
map(grouping_vars, group_by_at, .tbl = mtcars) %>%
  map(summarise,
      '6 cylinder' = sum(cyl == 6),
      'Large disp' = sum(disp >= 100),
      'low gears' = sum(gear <= 4))
#> [[1]]
#> # A tibble: 2 x 4
#>      vs `6 cylinder` `Large disp` `low gears`
#>   <dbl>        <int>        <int>       <int>
#> 1     0            3           18          14
#> 2     1            4            9          13
#> 
#> [[2]]
#> # A tibble: 2 x 4
#>      am `6 cylinder` `Large disp` `low gears`
#>   <dbl>        <int>        <int>       <int>
#> 1     0            4           19          19
#> 2     1            3            8           8
#> 
#> [[3]]
#> # A tibble: 6 x 4
#>    carb `6 cylinder` `Large disp` `low gears`
#>   <dbl>        <int>        <int>       <int>
#> 1     1            2            4           7
#> 2     2            0            8           8
#> 3     3            0            3           3
#> 4     4            4           10           9
#> 5     6            1            1           0
#> 6     8            0            1           0

reprex package(v0.2.1)于2019-05-02创建

原始答案

这是一个使用dplyr::groups()来找出哪些变量已分组的函数。然后迭代每个分组变量,汇总,并将结果数据框附加到列表中。

library(dplyr)

margins <- function(.data, ...) {
  groups <- dplyr::groups(.data)
  n <- length(groups)
  out <- vector(mode = "list", length = n)
  for (i in rev(seq_len(n))) {
    out[[i]] <-
      .data %>%
      dplyr::group_by(!!groups[[i]]) %>%
      dplyr::summarise(...) %>%
      dplyr::group_by(!!groups[[i]]) # Reapply the original group
  }
  out
}

mtcars %>%
  group_by(vs, am, carb) %>%
  margins('6 cylinder' = sum(cyl == 6),
          'Large disp' = sum(disp >= 100),
          'low gears' = sum(gear <= 4))
#> [[1]]
#> # A tibble: 2 x 4
#> # Groups:   vs [2]
#>      vs `6 cylinder` `Large disp` `low gears`
#>   <dbl>        <int>        <int>       <int>
#> 1     0            3           18          14
#> 2     1            4            9          13
#> 
#> [[2]]
#> # A tibble: 2 x 4
#> # Groups:   am [2]
#>      am `6 cylinder` `Large disp` `low gears`
#>   <dbl>        <int>        <int>       <int>
#> 1     0            4           19          19
#> 2     1            3            8           8
#> 
#> [[3]]
#> # A tibble: 6 x 4
#> # Groups:   carb [6]
#>    carb `6 cylinder` `Large disp` `low gears`
#>   <dbl>        <int>        <int>       <int>
#> 1     1            2            4           7
#> 2     2            0            8           8
#> 3     3            0            3           3
#> 4     4            4           10           9
#> 5     6            1            1           0
#> 6     8            0            1           0

reprex package(v0.2.1.9000)于2019-04-24创建

如果要使用变量名向量分组,可以使用dplyr::group_by_at()dplyr::vars()

cars_var <- c("vs", "am", "carb")

mtcars %>%
  group_by_at(vars(cars_var)) %>%
  margins('6 cylinder' = sum(cyl == 6),
          'Large disp' = sum(disp >= 100),
          'low gears' = sum(gear <= 4))

我是一个名为armgin的小程序包的作者,该程序包实现了此功能以及一些类似的想法。