使用列表来简化R中的代码

时间:2018-05-14 19:35:08

标签: r list vector functional-programming programmatically

背景:

大家好,

我希望你能帮我理解和理解。代码更上一层楼。我试图围绕列表,它们的好处,并使用它们来减少冗余代码。尽管我读到了关于列表和在线申请家庭的信息,但我仍然无法理解如何在我的日常工作中实施。

这是我可以大大简化的情况 - 这是我经常编写的代码类型,我希望用更简洁的格式替换。

实施例

让我们假装整个mtcars数据是一个观察年 - 比如说2018年。让我们假设我们的数据每年都会回溯到2000年。所以现在有“18”mtcars data.frames和一年列表示年份,我们将18个观察结果按行绑定到单个data.frame中。这是我正在使用的数据类型的示例。按年份分开的观察。

data <- mtcars %>%
group_by(date) %>%
  mutate(rank = dense_rank(desc(mpg))
         ))

数据操作我想简化:

  • 过滤:我想按不同的mpg等级过滤给定年份的所有内容

    数据%&gt;% 过滤器(gear == 4,date =='2005')%&gt;% 过滤器(在%c(1:5)中排名%)

    数据%&gt;% 过滤器(gear == 4,date =='2005')%&gt;% 过滤器(在%c(6:10)中排名%)

    数据%&gt;% 过滤器(gear == 4,date =='2005')%&gt;% 过滤器(在%c(11:15)中排名%)

简化上述冗余代码块的最佳方法是什么?

例如,我想使用seq函数并执行以下操作:

    data %>% 
filter(gear == 4, date == '2005') %>%
filter(rank %in% seq(1, 100, by = 5))

并将每个等级组的输出存储到列表中,然后在ggplot中绘制所有这些列表。

任何帮助或建议都会非常感激,我正在努力改善我的游戏。

1 个答案:

答案 0 :(得分:1)

学会以一种整洁的方式处理列表和列表列可能有点复杂。我非常推荐Jenny Bryan的purrr tutorial。在这里,您尝试避免需要为filteryeargear的不同值多次执行rank行。有几个步骤:

  1. 弄清楚如何获得所需值的所有组合。我们使用purrr::cross_df执行此操作,这是获取变量组合的一种非常方便的方法。
  2. 实际上为每个组合运行操作。因为我们的数据现在很好地设置为每行都是一组输入,所以我们可以使用pmap将每个过滤的数据集存储为列表元素。根据我们想要的情节,我们可以使用其他工具(如unnest)来实际将数据转换为我们想要绘制的格式。
  3. 我希望这可以说明一般来说,如果你发现你做了太多次,基本上有两个步骤;制作一个或多个可以迭代的列表,并使用map函数将所需的操作应用于每个列表元素。

    library(tidyverse)
    data <- mtcars %>%
      bind_rows(
        mtcars %>% mutate(year = 2005),
        mtcars %>% mutate(year = 2006)
        ) %>% 
      group_by(year) %>%
      mutate(rank = dense_rank(desc(mpg)))
    
    combos <- cross_df(list(
      year = 2005:2006,
      gear = 3:5,
      start = seq(1, 100, by = 5)
      ))
    
    combos %>%
      mutate(
        rank_range = map(start, ~ .x:(.x + 4)),
        filtered = pmap(
          .l = list(year, gear, rank_range),
          .f = ~ data %>%
            filter(gear == ..2, year == ..1) %>%
            filter(rank %in% ..3)
            )
        )
    #> # A tibble: 120 x 5
    #>     year  gear start rank_range filtered         
    #>    <int> <int> <dbl> <list>     <list>           
    #>  1  2005     3     1 <int [5]>  <tibble [0 x 13]>
    #>  2  2006     3     1 <int [5]>  <tibble [0 x 13]>
    #>  3  2005     4     1 <int [5]>  <tibble [4 x 13]>
    #>  4  2006     4     1 <int [5]>  <tibble [4 x 13]>
    #>  5  2005     5     1 <int [5]>  <tibble [2 x 13]>
    #>  6  2006     5     1 <int [5]>  <tibble [2 x 13]>
    #>  7  2005     3     6 <int [5]>  <tibble [2 x 13]>
    #>  8  2006     3     6 <int [5]>  <tibble [2 x 13]>
    #>  9  2005     4     6 <int [5]>  <tibble [6 x 13]>
    #> 10  2006     4     6 <int [5]>  <tibble [6 x 13]>
    #> # ... with 110 more rows
    

    reprex package(v0.2.0)创建于2018-05-14。