【问题标题】:Applying a Magrittr Pipe in lapply() with R使用 R 在 lapply() 中应用 Magrittr 管道
【发布时间】:2019-12-27 05:39:07
【问题描述】:

我想找到一种方法,通过 lapply 语句实现一系列管道函数,并由此生成多个数据库。这是一个示例数据集:

# the data
d <- tibble(
  categorical = c("a", "d", "b", "c", "a", "b", "d", "c"),
  var_1 = c(0, 0, 1, 1, 1, 0, 1, 0),
  var_2 = c(0, 1, 0, 0, 0, 0 ,1, 1),
  var_3 = c(0, 0, 1, 1, 1, 1, 1, 1),
  var_4 = c(0, 1, 0, 1, 0, 0, 0, 0)
)

这是我想要的结果:

$var_1
a  b  c  d
1  1  1  1

$var_2
a  b  c  d
0  0  1  2

$var_3
a  b  c  d
1  2  2  1

$var_4
a  b  c  d
0  0  1  1

我可以轻松地单独重新创建每个列表元素。这是我的 dplyr 示例代码:

d %>%
  filter(var_1 == 1) %>%
  group_by(categorical, var_1) %>%
  summarise(n = n()) %>%
  select(-var_1) %>%
  rename("var_1" = "n") %>%
  ungroup() %>%
  spread(categorical, var_1)

# A tibble: 1 x 4
      a     b     c     d
  <int> <int> <int> <int>
1     1     1     1     1

但是,我想跨所有列自动执行该过程,并创建一个对象,其中包含作为列表的每一行信息。

这是我开始的地方:

lapply(d[,2:5], function (x) d %>%
  filter(x == 1) %>%
  group_by(categorical, x) %>%
  summarise(n = n()) %>%
  select(-x) %>%
  rename("x" = "n") %>%
  ungroup() %>%
  spread(categorical, x))

任何帮助将不胜感激!

【问题讨论】:

    标签: r list dplyr magrittr


    【解决方案1】:

    我们可以将gather 转换为'long' 格式,然后在得到'val' 的sum 按'categorical' 分组后执行group_splitspread

    library(tidyverse)
    gather(d, key, val, -categorical) %>%
         split(.$key) %>%
         map(~ .x %>% 
               group_by(categorical) %>%
               summarise(val = sum(val)) %>%
               spread(categorical, val))
    #$var_1
    # A tibble: 1 x 4
    #      a     b     c     d
    #  <dbl> <dbl> <dbl> <dbl>
    #1     1     1     1     1
    
    #$var_2
    # A tibble: 1 x 4
    #      a     b     c     d
    #  <dbl> <dbl> <dbl> <dbl>
    #1     0     0     1     2
    
    #$var_3
    # A tibble: 1 x 4
    #      a     b     c     d
    #  <dbl> <dbl> <dbl> <dbl>
    #1     1     2     2     1
    
    #$var_4
    # A tibble: 1 x 4
    #      a     b     c     d
    #  <dbl> <dbl> <dbl> <dbl>
    #1     0     0     1     1
    

    或者另一种选择是遍历除第一个之外的列,然后将 group_by sumspread 执行为“宽”格式

    map(names(d)[-1], ~ 
              d %>%
               group_by(categorical) %>% 
               summarise(n = sum(!! rlang::sym(.x))) %>% 
               spread(categorical, n))
    

    【讨论】:

    • 第一个选项最适合我。我的实际数据集中有很多 NA 值,在gather 步骤之后添加na.omit() %&gt;% 效果很好。
    • @Craig 好的,在第二个版本中,您可以在sum 中使用na.rm = TRUE
    【解决方案2】:

    这是一个使用data.table::transpose() 的选项:

    aggregate(. ~ categorical, d, sum) %>%
      data.table::transpose(make.names = "categorical") %>%
      split(names(d)[-1])
    #> $var_1
    #>   a b c d
    #> 1 1 1 1 1
    #> 
    #> $var_2
    #>   a b c d
    #> 2 0 0 1 2
    #> 
    #> $var_3
    #>   a b c d
    #> 3 1 2 2 1
    #> 
    #> $var_4
    #>   a b c d
    #> 4 0 0 1 1
    

    reprex package 创建于 2019-11-04 (v0.3.0)

    【讨论】:

      猜你喜欢
      • 2017-10-02
      • 2018-07-23
      • 2015-03-12
      • 2018-04-29
      • 2016-05-22
      • 2022-11-04
      相关资源
      最近更新 更多