for(j in 2:length(loca)){

x<-max(se[loca[j-1]:loca[j],3])

}

这个循环结果只有最后一个结果,其他都被覆盖了,请问如何保存循环每一步的结果呢?谢谢

回复 第1楼 的 Ring:

<br />
x<- NULL<br />
for(j in 2:length(loca)){<br />
x <- rbind(x,max(se[loca[j-1]:loca[j],3]))<br />
}<br />
</p>

如果循环的次数很多,反复rbind会引起内存的反复new和delete,引发效率问题。

若循环次数已知,不如预先就定义好x的大小

<br />
x <- vector(mode="numeric", length=length(loca)-1)<br />
i=0<br />
for(j in 2:length(loca)){<br />
i=i+1;<br />
x[i] <- max(se[loca[j-1]:loca[j],3])<br />
}<br />
</p>
6 天 后

回复 第4楼 的 wangxiukun:

前几天拜读了不周山的博客,发现我的理解是错误的,

即使预定义了向量 x 的大小,但是在随后的 for 循环中,对 x 进行赋值, 依然会引发整个向量 x 的不断重新分配内存,反复 new 和 delete。


这太邪恶了!完全和C语言不同。这就是R中循环慢的根本原因。


所以提速的根本方法就是避免循环,采用向量计算。


回复 第5楼 的 doctorjxd:过了5天 ,自己又来推翻自己 赞一个,这样的人必然在不断进步.

回复 第5楼 的 doctorjxd:

事实远比你想像的要复杂,R也不是你想的那样邪恶。看下面的例子:

> x = 1:10<br />
> tracemem(x)<br />
[1] "<0x0db83e08>"<br />
><br />
> for(i in 1:10)<br />
+ {<br />
+     x[i] = i<br />
+     print(tracemem(x))<br />
+ }<br />
[1] "<0x0db83e08>"<br />
[1] "<0x0db83e08>"<br />
[1] "<0x0db83e08>"<br />
[1] "<0x0db83e08>"<br />
[1] "<0x0db83e08>"<br />
[1] "<0x0db83e08>"<br />
[1] "<0x0db83e08>"<br />
[1] "<0x0db83e08>"<br />
[1] "<0x0db83e08>"<br />
[1] "<0x0db83e08>"<br />
><br />
> x[1] = 1<br />
tracemem[0x0db83e08 -> 0x0d028db0]:<br />
> tracemem(x)<br />
[1] "<0x0d028db0>"<br />
</p>

这个例子说明,在循环赋值中,x的地址并没有发生改变,也就是说没有进行内存重分配。但是最后一句却发生了改变。为什么呢?

这里的邪恶之处在于,最初x = 1:10时,x是一个整数型向量,但后面x[1] = 1会使x向量变成double型,所以必须发生拷贝。而在循环中,i是整型变量,赋值给x时不会改变x的类型,内存也就没有发生改变。


总结起来就是三点:

1、改变向量类型一定会发生内存重分配;

2、改变向量长度一定会发生内存重分配;

3、上述两点都不变时,通常不会发生内存重分配。


所以,正确的做法依然是预先分配好长度。


回复 第7楼 的 Ihavenothing:

原来如此!这样才符合直觉。差一点走火入魔,偏执向量化。

多谢版主指点了。[s:11]

又学了如何跟踪内存地址。

<br />
> x=1:10<br />
> tracemem(x)<br />
[1] "<0x2b277518>"</p>
<p>> is.integer(x)<br />
[1] TRUE</p>
<p>> x[1]=1<br />
tracemem[0x2b277518 -> 0x2b2cd268]: </p>
<p>> is.integer(x)<br />
[1] FALSE</p>
<p>> x[1]=1L<br />
> tracemem(x)<br />
[1] "<0x2b2cd268>"<br />
></p>
<p>> is.integer(x)<br />
[1] FALSE</p>
<p>
</p>

回复 第8楼 的 doctorjxd:按照你的代码我这边一直换啊!

<br />
> x=1:10<br />
> tracemem(x)<br />
[1] "<0x070001a0>"<br />
> is.integer(x)<br />
[1] TRUE<br />
> x[1]=1<br />
tracemem[0x070001a0 -> 0x077bc0a0]:<br />
> is.integer(x)<br />
[1] FALSE<br />
> x[1]=1L<br />
tracemem[0x077bc0a0 -> 0x077bc008]:<br />
> tracemem(x)<br />
[1] "<0x077bc008>"<br />
> is.integer(x)<br />
[1] FALSE<br />
> x=as.integer(x)<br />
tracemem[0x06e82398 -> 0x0bc5d6a0]:<br />
> is.integer(x)<br />
[1] TRUE<br />
> x[1]=1L<br />
tracemem[0x0bc5d6a0 -> 0x0b6ce2f8]:<br />
</p>

回复 第9楼 的 suckbunny:神那,我早上还在看不周山的论文,看到下面有人评论说

x=1:10

x[1]=1L后地址还是会变的。试了一下,果然如此!!那个爆料的[s:13]看来就是兄台你了。

ps:看查了下《R语言编程艺术》中译版p268提到这个问题,如下代码中,z地址变化是有时发生,有时不发生的。我测试了一下是变化的,但是书里是没变化的。

z=runif(10)

tracemem(z)

z[3]=8

tracemem(z)

回复 第10楼 的 daigazi:并不是我哦~我也只是自己尝试了一下。发现有点地方不是很理解。另外不周山的博客我也看了,的确有人指出了类似的问题。

回复 第10楼 的 daigazi:

我又在Windows系统安装了R 2.14 和 3.0.1,试验了一下。地址都没有变化啊。只是类型不一致的时候才变。你用的什么版本及环境的R?

<br />
> z=runif(10)<br />
> tracemem(z)<br />
[1] "<0x01fb4308>"<br />
> z[3]=8<br />
> tracemem(z)<br />
[1] "<0x01fb4308>"<br />
</p>

回复 第12楼 的 doctorjxd:我这边是一旦变量发生地址变化,则就算类型一致也变化。R3.0.1,RSTUDIO

回复 第12楼 的 doctorjxd:

是说这个吗

<br />
 Sys.info()<br />
                     sysname                      release<br />
                   "Windows"                      "7 x64"<br />
                     version                     nodename<br />
"build 7601, Service Pack 1"                       "GAZI"<br />
                     machine                        login<br />
                    "x86-64"              "Administrator"<br />
                        user               effective_user<br />
             "Administrator"              "Administrator"<br />
</p>