【问题标题】:Looping over dplyr/ Function using dplyr使用 dplyr 循环 dplyr/函数
【发布时间】:2017-09-25 09:58:34
【问题描述】:

我已经创建了很多数据框,如下所示:

df <- data %>% select(var1,var2,var3,var4) %>% group_by(var3,var4) %>% filter(var2 ==1) %>% summarise(var1 = mean(var1))

这些数据帧中的每一个的输出是在将变量按 var3 和 var4 分组并根据不同的变量过滤后的 var1 的平均值。

我上面提供的数据框和我的代码中的其余部分的唯一区别是过滤变量。

因为我想要一张漂亮的表格来展示我的输出,所以我使用 left_join 来以我想要的方式合并和排列数据框。

虽然我已经完成了我的分析并得到了我想要的输出......

我必须用许多其他变量过滤变量,最后我创建了 20 个左右的数据框。

所以我的问题是:

还有其他方法可以使用函数或循环一次创建所有这些数据帧吗?类似的东西:

df[i]

也许我应该用我想过滤的变量定义和排列,然后命名这个数组?

欢迎任何想法!

提前致谢。

【问题讨论】:

    标签: r function loops dplyr


    【解决方案1】:

    因为您的过滤器似乎不是互斥的(也就是说,一个数据点可以位于多个过滤组中),我认为您最好的选择可能是制作一个过滤器的向量,然后循环遍历它矢量(虽然我会使用 lapply 而不是 for 循环)。

    由于您没有提供可重复的数据集或您使用的过滤器的想法,我将使用内置的 iris 数据并仅按物种分组(代码对于多个分组变量的工作方式相同)。

    首先,这是一组过滤器:

    irisFilters <-
      c(Long = quote(Sepal.Length > 6 | Petal.Length > 4)
        , Wide = quote(Sepal.Width > 3 | Petal.Width > 1.5)
        , Boxy = quote((Sepal.Width / Sepal.Length) > 0.5)
      )
    

    请注意,这些完全是任意的(并且可能根本没有意义),但它们应该让您了解什么是可能的。重要的是,我使用 quote 并不是为了让我以后可以将它们传递给 filter 步骤。

    然后,使用lapply 逐步检查每个过滤条件,使用!! 告诉 dplyr 解释变量内部的内容。在这里,我只是取Petal.Length 的平均值,因为这似乎与您的用例相匹配

    irisSummaries <-
      irisFilters %>%
      lapply(function(thisFilter){
        iris %>%
          filter(!! thisFilter) %>%
          group_by(Species) %>%
          summarise(Petal.Length = mean(Petal.Length))
      })
    

    这将返回一个列表,其中包含与您的每个条件匹配的汇总结果,如下所示:

    $Long
    # A tibble: 2 x 2
         Species Petal.Length
          <fctr>        <dbl>
    1 versicolor     4.502857
    2  virginica     5.552000
    
    $Wide
    # A tibble: 3 x 2
         Species Petal.Length
          <fctr>        <dbl>
    1     setosa     1.480952
    2 versicolor     4.730000
    3  virginica     5.572340
    
    $Boxy
    # A tibble: 3 x 2
         Species Petal.Length
          <fctr>        <dbl>
    1     setosa     1.462000
    2 versicolor     4.290909
    3  virginica     5.320000
    

    然后,您可以将它们组合到一个表中,使用您为它们分配的名称(在创建过滤器向量时)作为标识符:

    longSummaries <-
      irisSummaries %>%
      bind_rows(.id = "Filter")
    

    返回:

      Filter    Species Petal.Length
       <chr>     <fctr>        <dbl>
    1   Long versicolor     4.502857
    2   Long  virginica     5.552000
    3   Wide     setosa     1.480952
    4   Wide versicolor     4.730000
    5   Wide  virginica     5.572340
    6   Boxy     setosa     1.462000
    7   Boxy versicolor     4.290909
    8   Boxy  virginica     5.320000
    

    然后您可以使用spread 为每个过滤器创建一个列:

    wideSummaries <-
      longSummaries %>%
      spread(Filter, Petal.Length)
    

    返回:

         Species     Boxy     Long     Wide
    *     <fctr>    <dbl>    <dbl>    <dbl>
    1     setosa 1.462000       NA 1.480952
    2 versicolor 4.290909 4.502857 4.730000
    3  virginica 5.320000 5.552000 5.572340
    

    代码应该对任意数量的过滤器、您选择的任何名称、任意数量的分组变量(或组)都具有鲁棒性。如果您要返回多个变量,则需要更加小心,但在这种情况下,宽格式可能无论如何都是不可取的。

    【讨论】:

    • 很抱歉我的回复晚了,事实上很抱歉没有提供更多关于数据集的信息。我是这个世界的新手......但是,请允许我感谢您,因为您的解决方案非常出色并且节省了许多无用的代码行。没有更多的 cmets,因为我只是通过使用您的代码而无需进一步调整就复制了我想要的输出。非常感谢。
    • @Ioannis ,我很高兴它有所帮助。由于您是新手,这些可能会有所帮助。 How to make a great R reproducible exampleWhat should I do when someone answers my question?(投票和接受答案通常比评论更受欢迎;更容易量化。
    猜你喜欢
    • 1970-01-01
    • 2023-03-21
    • 2019-08-08
    • 2023-03-26
    • 1970-01-01
    • 1970-01-01
    • 2021-08-10
    • 2021-07-27
    • 1970-01-01
    相关资源
    最近更新 更多