【问题标题】:How to write loops "for" loops in R using dplyr syntax如何使用 dplyr 语法在 R 中编写循环“for”循环
【发布时间】:2017-01-09 20:46:04
【问题描述】:

我有一个在 R 中使用 dplyr 语法编写的大量代码。但是,我试图将该代码放入一个循环中,以便最终可以创建多个输出文件,而不仅仅是一个。不幸的是,我似乎无法这样做。

为了说明我的问题,让我们参考R中常用的“iris”数据集:

      > data("iris")
      > str(iris)
      'data.frame': 150 obs. of  5 variables:
      $ Sepal.Length: num  
      $ Sepal.Width : num  
      $ Petal.Length: num  
      $ Petal.Width : num  
      $ Species     : Factor w/ 3 levels "setosa","versicolor","virginica"

假设我想保存物种“杂色”的平均 Petal.Length。 dplyr 代码可能如下所示:

    MeanLength2 <- iris %>% filter(Species=="versicolor")
                       %>% summarize(mean(Petal.Length)) %>% print()

这将给出以下值:

      mean(Petal.Length)
    1               4.26

让我们尝试创建一个循环来获取所有物种的平均花瓣长度。

根据我对循环的了解,我想做这样的事情:

     for (i in unique(iris$Species))
      {
       iris %>% filter(iris$Species==unique(iris$Species)[i]) %>%
        summarize(mean(iris$Petal.Length)) %>% print()
        print(i) 
       }

出于某种原因,我必须在循环内指定数据框和列,而在使用 dplyr 的管道功能时通常不是这种情况。我假设这表明存在问题。

无论如何,上面的代码给出了以下输出:

          mean(iris$Petal.Length)
     1                   3.758
     [1] "setosa"
          mean(iris$Petal.Length)
     1                   3.758
     [1] "versicolor"
          mean(iris$Petal.Length)
     1                   3.758
     [1] "virginica"  

所以代码输出 3.758 三次,这是数据集中所有物种的平均花瓣长度。这表明“过滤器”代码没有按预期工作。据我所知,循环本身似乎按预期运行,因为所有三个独特的物种名称都打印在最终输出中。

如何使用 for 循环来做这样的事情?我知道这个特殊的练习不需要使用花哨的循环,因为可以通过使用例如 dplyr 中的“group_by”函数轻松获得所有物种的平均花瓣长度,但我希望输出接近100 个独特的表格和 PDF 文件以及我正在使用的数据集并知道如何使用 for 循环将真正有助于实现这一目的。

【问题讨论】:

  • 如果您真的需要为每个组提供单独的对象,那么使用group_by 然后split() 将结果放入一个列表中并为您想要的每个部分添加一个元素可能会更简单。跨度>
  • 感谢下面的代码。尽管我的数据集比我在这个问题中引用的虹膜数据更复杂,但我相信我可以利用您推荐的工作流程来做我想做的事情。
  • for循环的内部应该是iris %&gt;% filter(Species == i) %&gt;% summarize(mean(Petal.Length)) %&gt;% print()。这将使它为每个物种产生不同的数字。

标签: r loops dplyr


【解决方案1】:

很遗憾,您的代码没有引发任何错误。如果你逐行运行你的代码,你就会明白我在说什么。在本例中,我将选择循环的第一次迭代,让我们将 i 替换为 "setosa"

> iris  %>% filter(iris$Species == unique(iris$Species)["setosa"])
[1] Sepal.Length Sepal.Width  Petal.Length Petal.Width  Species     
<0 rows> (or 0-length row.names)

您的过滤器会生成一个没有观察结果的数据框,因此没有必要继续进行,但对于本示例,让我们运行其余代码:

> iris  %>% filter(iris$Species == unique(iris$Species)["setosa"]) %>%  
+ summarize(mean(iris$Petal.Length))
  mean(iris$Petal.Length)
1                   3.758

发生的情况是您从代码中调用 iris 数据集,更明显的示例是:

> filter(iris, iris$Species == unique(iris$Species)["setosa"]) %>% 
+ summarize(mean(mtcars$cyl))
  mean(mtcars$cyl)
1           6.1875

这就是为什么您没有得到预期的答案,您的过滤器不起作用并且您从另一个数据集中获得了汇总统计数据。

正如 TJ Mahr 所提到的,您的代码在没有指定数据集的情况下运行良好:

> for (i in unique(iris$Species))
+ {
+     iris %>% filter(Species==i) %>%
+         summarize(mean(Petal.Length)) %>% print()
+     print(i) 
+ }
  mean(Petal.Length)
1              1.462
[1] "setosa"
  mean(Petal.Length)
1               4.26
[1] "versicolor"
  mean(Petal.Length)
1              5.552
[1] "virginica"

希望对你有帮助

【讨论】:

    【解决方案2】:

    正如我在评论中提到的,如果您真的需要分离结果,使用group_by 然后split() 结果可能会更容易:

    iris %>% 
      group_by(Species) %>% 
      summarise(mn = mean(Petal.Length)) %>% 
      split(.,.$Species)
    
    $setosa
    # A tibble: 1 × 2
      Species    mn
       <fctr> <dbl>
    1  setosa 1.462
    
    $versicolor
    # A tibble: 1 × 2
         Species    mn
          <fctr> <dbl>
    1 versicolor  4.26
    
    $virginica
    # A tibble: 1 × 2
        Species    mn
         <fctr> <dbl>
    1 virginica 5.552
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-11-28
      • 2015-11-26
      • 2015-11-01
      • 2019-02-22
      • 2017-09-29
      • 2014-11-01
      • 2023-03-21
      • 1970-01-01
      相关资源
      最近更新 更多