我有一个想要对数据框的每一行运行的操作,更改了一列。我是一个apply/ddply/sqldf的人,但我会在有意义的时候使用循环,我认为这就是其中之一。这种情况很棘手,因为列的更改依赖于逐行更改的信息;根据一个单元格中的信息,我应该只对该行中其他十个单元格中的一个进行更改。对于75列和20000行,该操作需要10分钟,而我的脚本中的其他操作需要0-5秒,最多10秒。我已经将我的问题简化为下面非常简单的测试用例。
n <- 20000
t.df <- data.frame(matrix(1:5000, ncol=10, nrow=n) )
system.time(
for (i in 1:nrow(t.df)) {
t.df[i,(t.df[i,1]%%10 + 1)] <- 99
}
)对于10列,这需要70秒,如果为ncol=50,则需要360秒。这太疯狂了。循环是错误的方法吗?有没有更好、更有效的方法来做到这一点?
我已经尝试将嵌套项(t.dfi,1%%10 + 1)初始化为for循环外部的列表。它节省了大约30秒( 10分钟),但使上面的示例代码变得更加复杂。所以这是有帮助的,但这不是解决方案。
我目前最好的想法来自于准备这个测试用例。对我来说,只有10列是相关的( 75-11列是无关的)。由于运行时间在很大程度上取决于列数,因此我可以在排除不相关列的数据框上运行上述操作。这会让我降到一分钟多一点。但是,“带有嵌套索引的for循环”是思考我的问题的最佳方式吗?
发布于 2011-12-01 02:55:04
看起来真正的瓶颈是拥有data.frame形式的数据。我假设在您的实际问题中,您有一个令人信服的理由来使用data.frame。有没有办法把你的数据转换成一个矩阵呢?
顺便说一下,这是一个很好的问题,也是一个很好的例子。
下面是一个例子,说明在矩阵上循环比在data.frames上快得多:
> n <- 20000
> t.df <- (matrix(1:5000, ncol=10, nrow=n) )
> system.time(
+ for (i in 1:nrow(t.df)) {
+ t.df[i,(t.df[i,1]%%10 + 1)] <- 99
+ }
+ )
user system elapsed
0.084 0.001 0.084
>
> n <- 20000
> t.df <- data.frame(matrix(1:5000, ncol=10, nrow=n) )
> system.time(
+ for (i in 1:nrow(t.df)) {
+ t.df[i,(t.df[i,1]%%10 + 1)] <- 99
+ }
+ )
user system elapsed
31.543 57.664 89.224 https://stackoverflow.com/questions/8331132
复制相似问题