如何使用R包purrr中的函数重现循环

如何使用R包purrr中的函数重现循环,r,purrr,R,Purrr,我经常在代码中使用循环。我被告知,与其使用循环,不如使用函数,并且可以使用R包purr中的函数重新编写循环 作为一个例子,代码显示了虹膜数据集中不同物种的计数,其中萼片宽度

我经常在代码中使用循环。我被告知,与其使用循环,不如使用函数,并且可以使用R包purr中的函数重新编写循环

作为一个例子,代码显示了虹膜数据集中不同物种的计数,其中萼片宽度<3

 library(dplyr)
 #dataframe to put the output in
 sepaltable <- data.frame(Species=character(),
                     Total=numeric(), 
                     stringsAsFactors=FALSE) 

 #list of species to iterate over
 specieslist<-unique(iris$Species)

 #loop to populate the dataframe with the name of the species 
 #and the count of how many there were in the iris dataset

 for (i in  seq_along (specieslist)){
 a<-paste(specieslist[i])  
 b<- filter(iris,`Species`==a & Sepal.Width <=3)
 c<-nrow(b)
 sepaltable[i,"Species"]<-a
 sepaltable[i,"Total"]<-c
 }
库(dplyr)
#将输出放入其中的数据帧

可分离的我们可以在
dplyr

library(dplyr)
iris %>% 
   group_by(Species) %>%
   summarise(Total = sum(Sepal.Width <=3))

注意:
map
apply
系列函数(
lappy/sappy/vapply/rappy/mappy/map/apply
)都是循环

对于您提供的类型示例,akrun的答案是最直接的方法,特别是因为您已经在使用dplyr。dplyr包用于处理基本数据表摘要,尤其是示例中使用的组统计信息。
但是,在编写循环的大多数情况下,对于更复杂的情况,可以使用函数和apply族完成相同的任务

以您的例子:

# write function that does the stuff you put in your loop
summSpecies <- function(a) {
      b<- filter(iris,`Species`==a & Sepal.Width <=3)
      c<-nrow(b)
      return(c)
}

# apply the loop over your list
sapply(specieslist,summSpecies) #sapply simplifies the output to return a vector (in this case)
#[1]  8 42 33

# You can build this into a data frame
sepaltable <- data.frame(Species=specieslist,
                         Total=sapply(specieslist,summSpecies), 
                         stringsAsFactors=FALSE) 
sepaltable
#      Species Total
# 1     setosa     8
# 2 versicolor    42
# 3  virginica    33

毫不奇怪,为此类任务优化的现有功能显然是赢家。for-loop方法落后于apply-family方法

同意akrun-没有理由在此处实现purrr。如果要使用
purrr
,请将
sapply
替换为
map\u int
。在循环示例中,首先生成由循环填充的空数据帧。是否可以对该函数执行相同的操作,即该函数填充空数据帧,而不必在结尾将结果合并为向量?@Basil确定您可以先生成空数据帧,然后用例如
separatable$Total填充它
# write function that does the stuff you put in your loop
summSpecies <- function(a) {
      b<- filter(iris,`Species`==a & Sepal.Width <=3)
      c<-nrow(b)
      return(c)
}

# apply the loop over your list
sapply(specieslist,summSpecies) #sapply simplifies the output to return a vector (in this case)
#[1]  8 42 33

# You can build this into a data frame
sepaltable <- data.frame(Species=specieslist,
                         Total=sapply(specieslist,summSpecies), 
                         stringsAsFactors=FALSE) 
sepaltable
#      Species Total
# 1     setosa     8
# 2 versicolor    42
# 3  virginica    33
Unit: microseconds
#            expr      min        lq     mean   median        uq       max neval
#      ForLoop.OP 2548.519 2725.9020 3107.153 2819.837 3006.5915 11654.194   100
#     Apply.Brian 2385.638 2534.2390 2810.854 2625.050 2822.5145  9641.172   100
#     dplyr.akrun 721.136  837.6065 1180.244  864.604  902.9815 13440.076   100
#     purrr.akrun 3572.656 3783.2845 4147.900 3874.095 4073.5690 10517.602   100
#    purrr.Axeman 2440.973 2527.322 2866.7686 2586.8960 2774.097  9577.360   100