我有一个包含数千行的大型data.frame,我每次循环时都会从第1行创建一个子集,每次迭代增加一行。
在每个子集上,我执行了几个任务,这些任务来自对编程的pythonic理解,我执行'for'循环。例如。
df <- data.frame(a=c(1:10), b=c(11:20), c=c(21:30), d=c(31:40))
for (index in 1:nrow(df)) {
thisSubset <- df[1: index,]
#loop 1
new1 <- ncumeric(nrow(thisSubset))
for (i in 1:nrow(thisSubset)) {
var1 = 5 - thisSubset$b[i]
new1[i] <- 1/exp(var1*log(2));
}
#loop 2
new2 <- numeric()
for (i in 1:nrow(thisSubset)) if (thisSubset$c[i] >25) {
new2<- c(new2, (thisSubset$a[i]/exp(5*log(2))))
}
#loop 3
new3 <- numeric(nrow(thisSubset))
for (i in 1:nrow(thisSubset)) if (thisSubset$a[i] < 5) {
new3[i] <- thisSubset$d[i]-thisSubset$d[i+1]/2
} else {
new3[i] <- thisSubset$d[i]-thisSubset$d[i-1]/2
}
#loop x
#...
}
随着我的数据集变大,处理时间呈指数级增长到几个小时。我很欣赏在R中有更好的工作方式来执行类似的任务(例如应用),但是当每个循环中发生了几件事情以及每行使用多个元素时,我还能使用除“for”以外的任何东西吗?如果有人能给我一个上面提到的每个或任何循环的例子,我将不胜感激。
答案 0 :(得分:1)
For循环并不比它们的表兄弟更慢(事实上,有时它们甚至可以更快!)。真正的速度增益来自于尽可能将显式for循环转换为矢量化代码。例如,代码中的循环1和循环2可以转换为矢量化语句,如下所示:
#loop 1
new1 <- 1 / exp((5 - thisSubset$b) * log(2))
#loop 2
new2 <- thisSubset$a[thisSubset$c > 25] / exp(5 * log(2))
当你的计算取决于向量的索引(例如在循环3中)时,事物变得有点棘手,但是确实存在具有各种&#34;滚动&#34;的有效实现的包。函数(有关详细信息,请参阅roll
和zoo
包。)
如果您确实需要使用for循环,请记住,您应该始终预先分配您的&#34;结果&#34;在开始迭代之前的向量而不是在迭代期间增长它:
#bad
new2 <- numeric()
for (i in 1:nrow(thisSubset)) {
if (thisSubset$c[i] >25) {
new2<- c(new2, (thisSubset$a[i]/exp(5*log(2))))
}
}
#good
new2 <- numeric(length = nrow(thisSubset))
for (i in 1:nrow(thisSubset)) {
if (thisSubset$c[i] >25) {
new2[i] <- (thisSubset$a[i]/exp(5*log(2)))
}
}
这可以防止R在每次迭代后复制new2
,从而产生更快的代码。
答案 1 :(得分:0)
R是一种矢量化语言,因此大多数函数可以在单个语句中应用于整个列,而不会向下迭代每一行。例如,我向你的三个内部循环进行了矢量化:
df <- data.frame(a=c(1:10), b=c(11:20), c=c(21:30), d=c(31:40))
thisSubset <- df
#loop 1
new1 <- numeric(nrow(thisSubset))
var1 = 5 - thisSubset$b
new1 <- 1/exp(var1*log(2));
#loop 2
new2 <- numeric()
new2<- (thisSubset$a[thisSubset$c >25]/exp(5*log(2)))
#loop 3
new3 <- numeric(nrow(thisSubset))
dplus1 <-c(thisSubset$d[-1], thisSubset$d[length(thisSubset$d)])
dminus1 <-c(thisSubset$d[1], thisSubset$d[-length(thisSubset$d)])
new3<- ifelse((thisSubset$a < 5), thisSubset$d-dplus1/2, thisSubset$d-dminus1/2)
#loop x
#...
你的外环是不必要的 有关其他评论,请参阅Mark的解决方案。