在R中循环更新变量

时间:2011-11-25 21:37:37

标签: r

如何修改代码以更新循环中的变量?

具体来说,我想做类似以下的事情:

myMatrix1 <- read.table(someFile)
myMatrix2 <- read.table(someFile2)

for (i in nrow(myMatrix2))
{       
    myMatrix3 <- myMatrix1[which(doSomeTest),]
    myMatrix4 <- rep(myMatrix2$header1,nrow(myMatrix1)) 
    myMatrix5 <- rep(myMatrix2$header2, nrow(myMatrix1))        
    myMatrix6 <- cbind(myMatrix3, myMatrix4, myMatrix5) 
    # *see question

}

如何更新myMatrix6而不是重新分配cbind(myMatrix3, myMatrix4, myMatrix5)的产品?换句话说,如果第一次迭代(i = 1)给出myMatrix6:

> 1   1    1   1
> 2   2    2   2

并且第二次迭代(i = 2)给了myMatrix 6:

> 3   3    3   3
> 4   4    4   4

如何获得以下数据帧(?):

> 1   1    1   1
> 2   2    2   2
> 3   3    3   3
> 4   4    4   4

更新:

我有 - 感谢DWin和Timo的建议 - 得到了以下内容。但是,以下代码花了我大约2个小时来运行我的数据集。有没有办法让它运行得更快??? (不使用我可能添加的更强大的计算机)

# create empty matrix for sedimentation
myMatrix6 <- data.frame(NA,NA,NA,NA)[0,]
names(myMatrix6) <- letters[1:4]

# create empty matrix for bore
myMatrix7 <- data.frame(NA,NA,NA,NA)[0,]
names(myMatrix7) <- letters[1:4]

for (i in 1:nrow(myMatrix2))
{       
    # create matrix that has the value of myMatrix1$begin being 
    # situated between the values of myMatrix2begin[i] and myMatrix2finish[i]
    myMatrix3 <- myMatrix1[which((myMatrix1$begin > myMatrix2$begin[i]) & (myMatrix1$begin < myMatrix2$finish[i])),]

    myMatrix4 <- rep(myMatrix2$sedimentation, nrow(myMatrix3))

    if (is.na(myMatrix2$boreWidth[i])) {
        myMatrix5 <- rep(NA, nrow(myMatrix3))
    }
    else if (myMatrix2$boreWidth[i] == 0) {
        myMatrix5 <- rep(TRUE, nrow(myMatrix3))
    }
    else if (myMatrix2$boreWidth[i] > 0) {
        myMatrix5 <- rep(FALSE, nrow(myMatrix3))
    }

    myMatrix6 <- rbind(myMatrix6, cbind(myMatrix3, myMatrix4))
    myMatrix7 <- rbind(myMatrix7, cbind(myMatrix3, myMatrix5))
}

2 个答案:

答案 0 :(得分:2)

您改为将myMatrix6初始化为空data.frame并对结果进行rbind(可能效率低下)。如果效率是一个问题,那么你预先分配你想要的大小,并在data.frame中用索引填充行。

# Method # 1 code
myMatrix6 <- data.frame(NA,NA,NA,NA)[0,]
names(myMatrix6) <- letters[1:4]

for (i in nrow(myMatrix2)) {       
    myMatrix3 <- myMatrix1[which(doSomeTest),]
    myMatrix4 <- rep(myMatrix2$header1,nrow(myMatrix1)) 
    myMatrix5 <- rep(myMatrix2$header2, nrow(myMatrix1))        
    myMatrix6 <- rbind( myMatrix6, cbind(myMatrix3, myMatrix4, myMatrix5) )
                           }

答案 1 :(得分:1)

在你的代码中,你不处理矩阵(在R的意义上),但数据帧,read.table返回一个数据帧。

无论哪种方式,您都可以使用rbind命令将一个矩阵/数据框附加到另一个(假设列名称匹配)

例如,如果

> a = data.frame(x=c(1,2,3),y=c(4,5,6),z=c(7,8,9))
> b = data.frame(x=c(4,5),y=c(5,6),z=c(6,7))

然后

> rbind(a,b)
  x y z
1 1 4 7
2 2 5 8
3 3 6 9
4 4 5 6
5 5 6 7

您提供的代码中还有其他问题。例如

for (i in length(someVector)))

应该是

for (i in 1:length(someVector)))

R具有许多用于迭代data.frames,向量等的函数,并且可以进行各种数据转换。大多数情况下,不需要编写for循环。

如果您想提供有关您尝试做什么的更多详细信息,也许我们可以找到更简单的解决方案。

编辑:

从您的帖子更新中可以看出,您尝试在“宽”和“长”格式之间进行某种转换,并过滤掉一些未通过测试的行。如果我错了,请纠正我。

无论如何,如果是这种情况,你应该检查reshape命令。此外,还有一个reshape包,其中包含非常有用的命令meltcast,可以非常有效地执行此类转换。此外,还有merge命令用于对数据帧执行某些“连接”操作。我很确定你的问题可以通过使用上述命令的组合来解决,但这取决于具体的细节。

要使用某些条件过滤行/列,请查看subset命令。