何时使用apply函数

时间:2015-03-18 19:08:20

标签: r for-loop apply

说我有类似的东西:

# Create some data:
treatment <- round(runif(20, min = 0, max = 1),0)
d2 <- round(runif(20, min = 0, max = 1),0)
bxd2 <- treatment * d2
infection <- round(runif(20, min = 0, max = 100),0) 
lung <- round(runif(20, min = 0, max = 100),0) 
head <- round(runif(20, min = 0, max = 100),0) 

df <- data.frame(treatment, d2, bxd2, infection, lung, head)

rm(treatment, d2, bxd2, infection, lung, head)


reg_func <- function(i,data){
form <- paste(colnames(df)[i+3], c("treatment + d2 + bxd2"), sep = "~") 
form <- as.formula(form)
print(lm(form, data = data))
}

for (i in 1:3) {
name <- paste0("reg", i)
assign(name, reg_func(i, df))
}

现在这样按照我想要的方式工作,我最终得到reg1,...,regN在工作区中分配(坏习惯,但对计量经济学很有效)。

我现在的问题是:为什么我要将(如上所述)转变为应用实例? for循环似乎很容易,但我听到有人说'#34; ...你应该真的使用[X] apply&#34;。

3 个答案:

答案 0 :(得分:0)

速度不快:

> a <- seq(300)
> system.time(replicate(1000, sapply(a ,mean)))
   user  system elapsed 
  2.215   0.000   2.216 
> v <- c()
> system.time(replicate(1000, for(i in a){v <- c(v,mean(i))}))
   user  system elapsed 
  2.315   0.000   2.315 

但它可以防止这种情况发生:

> i <- 1
> for(i in a) mean(i)
> i
[1] 300

它让事情变得干净整洁:

> sapply(a ,mean)
> ls()
[1] "a"  
> for(i in a) mean(i)
> ls()
[1] "a"    "i"    

答案 1 :(得分:0)

简短的回答是不要担心使用循环。使用apply的主要原因是,首先,在某些情况下,它可以更有效,其次,它使代码更清晰。

但有时它并没有使代码更清晰。例如,如果您确实需要一组名为reg1 reg2等的变量而不是名为reg的列表,那么您的版本将更清晰。而且由于每次循环都在进行回归,因此性能差异很小,因为大部分工作都在回归而不是循环,无论你如何编码。

现在,我认为名称为reg的列表是存储这些结果的更有用的方法,原因很多。例如,如果要遍历它们,则可以执行reg[[i]]而不是粘贴字符串。但听起来你已经考虑过这个问题并决定将这些变量命名为这个原因。

答案 2 :(得分:0)

是的,apply()真的不能更快:

> mat <- matrix(rnorm(1000 * 1000), nrow = 1000)
> system.time({
+     v <- numeric(1000)
+     for (i in 1:1000) v[i] <- mean(mat[i, ])
+ })
## user  system elapsed 
## 0.021   0.001   0.023 
>
> system.time(apply(mat, 1, mean))
## user  system elapsed 
## 0.021   0.001   0.022

对于矩阵,如果你采取什么手段,这可能会更好:

> system.time(rowMeans(mat))
## user  system elapsed 
## 0.003   0.000   0.003 

但是对于列表和数据框,lapply()sapply()可以更快:

> system.time({
+     v <- numeric(1000)
+     for (i in 1:1000) v[i] <- mean(df[[i]])
+ })
## user  system elapsed 
## 0.015   0.000   0.016 
>
> system.time(sapply(df, mean))
## user  system elapsed 
## 0.008   0.000   0.008

因为R是一种脚本语言,速度通常比C ++等低级语言慢。所以如果可能的话,使用嵌入了二进制代码或字节代码的这些函数,它将保存