• R语言
  • 发个学习贴,新手可以进来看看一些问题的理解

27.which()函数进阶

前面讲过例如:

R>vm=c(3,1,2,4,6)<br />
R>which(vm%%3==0)<br />
[1] 1 5


这个当VM是向量时的情况,返回了INDEX,但是我们看看矩阵的情况:
R>m=matrix(1:12,3,4)<br />
R>m<br />
     [,1] [,2] [,3] [,4]<br />
[1,]    1    4    7   10<br />
[2,]    2    5    8   11<br />
[3,]    3    6    9   12<br />
R>which(m%%3==0)<br />
[1]  3  6  9 12<br />
R>which(m%%3==0,arr.ind=TRUE)<br />
     row col<br />
[1,]   3   1<br />
[2,]   3   2<br />
[3,]   3   3<br />
[4,]   3   4


我们看到直接用which只返回矩阵中那些被3整除的值,不返回INDEX,加了参数arr.ind=TRUE(很好记,就是array.index的简写嘛,记是这样记,打还必须是代码里的)就可以了
</p>

28.order()函数进阶

先做好一些准备:

R>x=c(1,2,1,3,2,5)<br />
R>y=c(1,3,2,4,2,6)<br />
R>z=c(1:6)<br />
R>a=rbind(x,y,z)<br />
R>a<br />
  [,1] [,2] [,3] [,4] [,5] [,6]<br />
x    1    2    1    3    2    5<br />
y    1    3    2    4    2    6<br />
z    1    2    3    4    5    6<br />
R>class(a)<br />
[1] "matrix"


这个时候如果我们想要对a这个矩阵按照x的升序排列,怎么办?
R>ii=order(x,y,z)<br />
R>a[,ii]<br />
  [,1] [,2] [,3] [,4] [,5] [,6]<br />
x    1    1    2    2    3    5<br />
y    1    2    2    3    4    6<br />
z    1    3    5    2    4    6


大家注意到这个时候a就按x升序排了,y,z的值全都是对应的

如果是按x降序呢?
R>iii=order(-x,y,z)<br />
R>a[,iii]<br />
  [,1] [,2] [,3] [,4] [,5] [,6]<br />
x    5    3    2    2    1    1<br />
y    6    4    2    3    1    2<br />
z    6    4    5    2    1    3


其实大家到这里仔细看看上面2个排序后的y,z,就会注意到,order(x,y,z)这里的排序,是先对x从小到大排,排完后,在x相同的值里面,再按y从小到大排,同理order(-x,y,z),那么,现在大家可以想想order(x,-y,z)又是什么意思呢?哈哈

到了这里,大家基本上就了解了order()了,下面再说下,如果a里面有NA怎么办?(NA与NULL见学习帖1)

先做些准备:
R>a=c(1,3,2,NA)<br />
R>b=c(NA,2,4,7)<br />
R>c=cbind(a,b)<br />
R>c<br />
      a  b<br />
[1,]  1 NA<br />
[2,]  3  2<br />
[3,]  2  4<br />
[4,] NA  7<br />
R>class(c)<br />
[1] "matrix"


这里新手们也可以看看rbind,cbind的区别

我们先看默认情况:
R>ii=order(a,b)<br />
R>c[ii,]<br />
      a  b<br />
[1,]  1 NA<br />
[2,]  2  4<br />
[3,]  3  2<br />
[4,] NA  7<br />
R>


再看加参数的情况:
R>iii=order(a,b,na.last=FALSE)<br />
R>c[iii,]<br />
      a  b<br />
[1,] NA  7<br />
[2,]  1 NA<br />
[3,]  2  4<br />
[4,]  3  2<br />
R>iiii=order(a,b,na.last=NA)<br />
R>c[iiii,]<br />
     a b<br />
[1,] 2 4<br />
[2,] 3 2<br />
R>


好了,到了这里,order()这个函数大家应该都比较熟悉了,便于以后我们对数据矩阵进行精确控制,毕竟大多数时候我们分析的对象都是数据矩阵嘛!
</p>

29.sort()函数进阶

这里贴出一个帖子,然后弄清楚要做什么之后,看看14楼的代码

http://cos.name/cn/topic/110139#post-246053

17 天 后

30.几个编辑命令

首先,在R-console中我们可以在"help"->"console"里找到这一帮助文档,里面很全:

我列几个常用的:

1)ctrl+L 清空控制台

2)ctrl+U 清空光标所在的当前行

3)ctrl+DEL 清空光标所在处直行尾

回复 第13楼 的 iamstomach:

<br />
> for(i in 1:3){<br />
+ print("select ",i)<br />
+ }<br />
[1] "select "<br />
[1] "select "<br />
[1] "select "<br />
> for(i in 1:3){<br />
+ print(paste("select ",i))<br />
+ }<br />
[1] "select  1"<br />
[1] "select  2"<br />
[1] "select  3<br />


看来R的print函数还真是奇怪,要循环输出i,还必须借助paste
</p>

回复 第17楼 的 superdesolator:

<br />
> d[order(d$ages),]<br />
  kids ages<br />
2    b    0<br />
1    a    2<br />
3    c    4<br />
> d[,order(d$ages)]<br />
Error in <code>[.data.frame</code>(d, , order(d$ages)) : undefined columns selected<br />


只能调用行,却无法调用列。不知为何
</p>

回复 第18楼 的 superdesolator:只需要一个"\n"即可。

31.关于.Rprofile,.Renviron,.First,.Last,options的用法初步

首先,这是一篇菜鸟进阶贴,了解下面的内容,你将对R的熟悉提升一个档次(windows),但仅了解下面的还是一个菜鸟。。。

一般我们只能通过CMD创建.开头的.Rprofile,.Renviron隐藏文件,这里我们使用默认的Rprofile.site,Renviron.site来说,功能一样,1.Renviron.site我不想多说,因为我不了解,只看下面一个代码:

R_LIBS=C:/R/library

就是说设置R的安装包的路径,要了解这个Renviron.site的设置,前提无疑是你需要精通变量的意思和各种各样的变量你才能设置好,这个不适合新手

2.Rprofile.site这个对于我们新手才是暂时的主攻点,上面Renviron.site里设置的都是变量,这里我们设置的都是Rcode,比较常用的有options的设置和.First,.Last的设置,

(在下面的代码前不要加#)大家可以试试看:

options(prompt="R>")

old <- getOption("defaultPackages");

options(defaultPackages = c(old, "MASS"))

.First <- function() {

setwd("C:\\Users\\Administrator\\Desktop\\Rworkspace")}

等等,我们就可以设置很多了,我现在才想起谢老大说的,这对新手是地狱,对高手是天堂的意思了,不过我还是处于地狱。。。

有了上面的一些示例,大家可以试着设置自己的下载包的镜像,从而避免每次都要选择(谢老大的忍者必修有提示)

3..Rdata,这是一个下个帖子要说的保存空间,也就是每次你关闭R前总问你的那个

4..First

基本上R的启动就是按这样的顺序找Renviron.site->Rprofile.site(不找.First)->

.Rdata->.First(应该是这样,即使错了,新手这样理解下吧,等哪天成大牛了,再来纠正我吧)

而.Last是在quit前执行,用法和.First一样

基本上就是这样的一个流程,用的好不好,接下来就要看你多了解windows,变量,options等等了

PS;Rprofile.site,Renviron.site在你安装的R的etc中,可以用文本文件方式打开,或者在RConsole用file.edit(‘绝对路径名')打开编辑

32.source(),sink(),save.image(),history()的用法初步

1.source("文件绝对路径名.r")

如果你是在当前工作空间的话,直接文件名就OK

2.sink("文件绝对路径名")

可以把输出结果输到那个文件

3.save.image()就可以保存结果到.Rdata也就是工作空间

大家可以输入我从RD上转来的一段代码体会体会:

x <- stats::runif(20)

y <- list(a = 1, b = TRUE, c = "oops")

save(x, y, file = "xy.RData")

save.image()

unlink("xy.RData")

unlink(".RData")

4.history(20)你之前打得20行代码

loadhistory(file = ".Rhistory")

savehistory(file = ".Rhistory")

这大家一看就懂了吧!

这里大家结合上一贴的话就可以实现个蛮实用的功能就是退出R的时候自动保存你输入过的代码到指定地方:

.Last <- function()

if(interactive()) try(savehistory("~/.Rhistory"))

PS:这里再稍微总结下source()呢就是别人写好一个.r给你,你可以直接source到你的R里,而savehistory呢就是你把你之前输入过的代码全都保存下来了,以后直接loadhistory就可以用了,最后save.image()谁用谁知道!从哪里结束的,第二天接着从哪里继续用呗。。。

个人提个小小的建议,谢老大做knitr的初衷不就是因为赋值黏贴代码的时候“>”这个很讨厌吗,帅哥你偏偏在每行前面都加一个R>,复制黏贴的时候那叫一个难受啊。

回复 第51楼 的 daigazi:呵呵,那是因为我还没有到觉得它讨厌的水平...[s:18]

33.debug简单初步

下面主要内容来自R语言艺术一书

问题背景找x=c(1,0,0,1,1,0,1,1,1)中连续的1的下标,并且几个连续可以由k设置,比如k=2的时候,x中应返回4,7,8

因为4,5;7,8;8,9;

准备代码(有错误,我们要调试出来):

 findruns <- function(x,k) {<br />
 n <- length(x)<br />
 runs <- NULL<br />
 for (i in 1:(n-k)) {<br />
 if (all(x[i:i+k-1]==1)) runs <- c(runs,i)</p>
<p> }<br />
return(runs)<br />
}
</p>

调试(注意每次修改findruns.r都要重新source,debug中n代表下步,循环时c代表下个循环,setBreakpoint(),browser()的用法大概是类似断点,具体看代码,Q退出本次调试,undebug()退出调试):

<br />
R>source("findruns.r")<br />
R>x=c(1,0,0,1,1,0,1,1,1);k=2<br />
R>findruns(x,k)<br />
[1] 3 4 6 7<br />
R>debug(findruns)<br />
R>findruns(x,k)<br />
debugging in: findruns(x, k)<br />
debug at findruns.r#1: {<br />
    n <- length(x)<br />
    runs <- NULL<br />
    for (i in 1:(n - k)) {<br />
        if (all(x[i:i + k - 1] == 1))<br />
            runs <- c(runs, i)<br />
    }<br />
    return(runs)<br />
}<br />
Browse[2]> n       #往下步走<br />
debug at findruns.r#2: n <- length(x)<br />
Browse[2]> n<br />
debug at findruns.r#3: runs <- NULL<br />
Browse[2]> n<br />
debug at findruns.r#4: for (i in 1:(n - k)) {<br />
    if (all(x[i:i + k - 1] == 1))<br />
        runs <- c(runs, i)<br />
}<br />
Browse[2]> a=1;b=2;a+b #debug中可以任意使用R代码<br />
[1] 3<br />
Browse[2]> n<br />
debug at findruns.r#4: i<br />
Browse[2]> n<br />
debug at findruns.r#5: if (all(x[i:i + k - 1] == 1)) runs <- c(runs, i)<br />
Browse[2]> i       #来到第一次循环<br />
[1] 1<br />
Browse[2]> k<br />
[1] 2<br />
Browse[2]> x[i:i+k-1]应该输出x[1:1+2-1],x[1:2]即1,0<br />
Error: unexpected symbol in "x[i:i+k-1]应该输出x"<br />
Browse[2]> x[i:i+k-1]#应该输出x[1:1+2-1],x[1:2]即1,0<br />
[1] 0<br />
Browse[2]> #实际输出了0,有问题!于是我们<br />
Browse[2]> i:i+k-1 #应该输出1:2<br />
[1] 2<br />
Browse[2]> #实际是2,原来发现丢了括号。。回到finruns.r中修改<br />
Browse[2]> Q<br />
R>file.edit("findruns.r")<br />


第一次修改后,
  if (all(x[i:(i + k - 1)] == 1))<br />


我们这里可以用setBreakpoints()设置断点,直接跳过我们前面已经调试的4行,直接从第5行循环开始:
R>setBreakpoint("findruns.r",5)<br />
R>findruns(x,k)<br />
findruns.R#5<br />
Called from: findruns(x, k)<br />
Browse[1]> i<br />
[1] 1<br />
Browse[1]> x[i:(i+k-1)]<br />
[1] 1 0<br />
Browse[1]> c<br />
findruns.R#5<br />
Called from: findruns(x, k)<br />
Browse[1]> i<br />
[1] 2<br />
Browse[1]> x[i:(i+k-1)]<br />
[1] 0 0<br />
Browse[1]> #发现每步循环都正确


但,继续算的时候发现仍然错误
R>source("findruns.r")<br />
R>findruns(x,k)<br />
[1] 4 7<br />
R>


所以继续调试,这里需要涉及到browser()了,它的大概意思就是从你设置的条件+browser()处开始调试,由于前面我们知道debug是用n,c进行一步一步调试,为了直接跳到循环的哪步,我们就必须设置断点:
R>source("findruns.r")<br />
R>findruns(x,k)  #注意由于我们已经设置了browser(),所以不要用debug(),否则从头开始调试<br />
Called from: findruns(x, k)<br />
Browse[1]> i   #这个时候我们再来看看最后个i<br />
[1] 7<br />
Browse[1]> #可以知道我们应该有9个元素,k=2的话应该循环到8,所以这里就发现错误了<br />
Browse[1]> #for (i in 1:(n - k))这里应该是for (i in 1:(n-k+1)),修改后再试<br />
Browse[1]><br />

R>source("findruns.r")<br />
R>findruns(x,k)<br />
[1] 4 7 8<br />
R>


成功了!!

PS;第2个例子我就不说了,注意options(error=recover),where其余差不多。。

至于什么trace(),以及debug的包需要等大神来讲,或者我们以后摸索了
</p>

34.s3classes初步

这无疑是篇进阶贴,从2个月前完全看不懂,到现在能领悟一些感觉,其中苦乐,真的是满脸都是泪。。。

好吧,为了了解S3classes我们先来了解R中vector,我们都该知道R中一个vector中数据类型必须一致,但如果不一致怎么办呢,用list().

R>x=c("r",1) #尝试不同类型放入一个向量x<br />
R>x<br />
[1] "r" "1"<br />
R>class(x)  #看看x是什么类型<br />
[1] "character"<br />
R>#发现数字1被强制转换成字符型了<br />
R>x=list("r",1)<br />
R>x<br />
[[1]]<br />
[1] "r"</p>
<p>[[2]]<br />
[1] 1</p>
<p>R>class(x)<br />
[1] "list"<br />
R>#输出结果不一样,可以放入不同类型到list里去,有C基础的同学会容易联想到struct,其实意思差不多<br />


了解了list后我们再来看看R中的一些分析结果是怎么看的:
<br />
R>x=1:9<br />
R>y=2:10<br />
R>z=lm(y~x)<br />
R>z      #这句与print(z)等价</p>
<p>Call:<br />
lm(formula = y ~ x)</p>
<p>Coefficients:<br />
(Intercept)            x<br />
          1            1  </p>
<p>R>class(z)<br />
[1] "lm"<br />
R><br />


这里z的class是"lm",先不急着分析,我们再来看看什么是print(),学过C++重载,多态概念的同学可能好理解(这也是为什么我看过一边C++基础后才能写出这部分内容),我们通常print一个数字也可以,print一个字符也可以,但只需要用print就可以了,类似的还有summary().这是为什么呢?

其实当你print(z)的时候,R就找z的class,然后根据class(z)="numeric"还是"character"决定调用print.numeric(当然不一定有这个,我只是形象举例),还是print.character,这里R知道(说了z,和print(z)一样)哦,原来z是一个叫"lm"的class,然后它就调用print.lm,下面我们来看看这个的具体代码是什么:
R>print.lm<br />
function (x, digits = max(3L, getOption("digits") - 3L), ...)<br />
{<br />
    cat("\nCall:\n", paste(deparse(x$call), sep = "\n", collapse = "\n"),<br />
        "\n\n", sep = "")<br />
    if (length(coef(x))) {<br />
        cat("Coefficients:\n")<br />
        print.default(format(coef(x), digits = digits), print.gap = 2L,<br />
            quote = FALSE)<br />
    }<br />
    else cat("No coefficients\n")<br />
    cat("\n")<br />
    invisible(x)<br />
}<br />
<bytecode: 0x05ad5350><br />
<envi


这段代码聪明的人会恍然大悟,原来输出的什么call,coefficients格式全都通过print.lm这个函数设置好了!

那么我们unclass(z)让z没有"lm"这个类名称看看会有什么:
R>unclass(z)<br />
$coefficients<br />
(Intercept)           x<br />
          1           1 </p>
<p>$residuals<br />
            1             2             3             4             5<br />
 6.421462e-16 -1.463870e-15  2.575398e-16  2.160477e-16  7.762798e-17<br />
            6             7             8             9<br />
 4.247140e-16  5.495385e-16 -1.992870e-16 -5.044570e-16 </p>
<p>$effects<br />
  (Intercept)             x<br />
-1.800000e+01  7.745967e+00  2.636780e-16  5.551115e-17 -2.495833e-16 </p>
<p>-6.917210e-17 -1.110223e-16 -1.026523e-15 -1.498367e-15 </p>
<p>$rank<br />
[1] 2</p>
<p>$fitted.values<br />
 1  2  3  4  5  6  7  8  9<br />
 2  3  4  5  6  7  8  9 10 </p>
<p>$assign<br />
[1] 0 1</p>
<p>$qr<br />
$qr<br />
  (Intercept)             x<br />
1  -3.0000000 -1.500000e+01<br />
2   0.3333333  7.745967e+00<br />
3   0.3333333  1.290994e-01<br />
4   0.3333333 -2.866584e-17<br />
5   0.3333333 -1.290994e-01<br />
6   0.3333333 -2.581989e-01<br />
7   0.3333333 -3.872983e-01<br />
8   0.3333333 -5.163978e-01<br />
9   0.3333333 -6.454972e-01<br />
attr(,"assign")<br />
[1] 0 1</p>
<p>$qraux<br />
[1] 1.333333 1.258199</p>
<p>$pivot<br />
[1] 1 2</p>
<p>$tol<br />
[1] 1e-07</p>
<p>$rank<br />
[1] 2</p>
<p>attr(,"class")<br />
[1] "qr"</p>
<p>$df.residual<br />
[1] 7</p>
<p>$xlevels<br />
named list()</p>
<p>$call<br />
lm(formula = y ~ x)</p>
<p>$terms<br />
y ~ x<br />
attr(,"variables")<br />
list(y, x)<br />
attr(,"factors")<br />
  x<br />
y 0<br />
x 1<br />
attr(,"term.labels")<br />
[1] "x"<br />
attr(,"order")<br />
[1] 1<br />
attr(,"intercept")<br />
[1] 1<br />
attr(,"response")<br />
[1] 1<br />
attr(,".Environment")<br />
<environment: R_GlobalEnv><br />
attr(,"predvars")<br />
list(y, x)<br />
attr(,"dataClasses")<br />
        y         x<br />
"numeric" "numeric" </p>
<p>$model<br />
   y x<br />
1  2 1<br />
2  3 2<br />
3  4 3<br />
4  5 4<br />
5  6 5<br />
6  7 6<br />
7  8 7<br />
8  9 8<br />
9 10 9</p>
<p>R>


这个时候很多人会哇,原来这样,是的,lm()返回了很多东西,但是R的作者力求简洁,所以我们z或者print(z)出来的东西不多,原因上面也贴出了是print.lm这个函数的问题!而不了解真相的初学者会想"切!就这种结果么?SAS好多了。。"

好吧,我们继续,上面说了lm()返回了很多结果,我们就来看看lm():
R>lm<br />
function (formula, data, subset, weights, na.action, method = "qr",<br />
    model = TRUE, x = FALSE, y = FALSE, qr = TRUE, singular.ok = TRUE,<br />
    contrasts = NULL, offset, ...)<br />
{<br />
    ret.x <- x<br />
    ret.y <- y<br />
    cl <- match.ca<br />
.....<br />
z <- list(coefficients = if (is.matrix(y)) matrix(, 0,<br />
            3) else numeric(), residuals = y, fitted.values = 0 *<br />
            y, weights = w, rank = 0L, df.residual = if (!is.null(w)) sum(w !=<br />
            0) else if (is.matrix(y)) nrow(y) else length(y))<br />
....<br />
 class(z) <- c(if (is.matrix(y)) "mlm", "lm")<br />
..<br />


大家可以看到,lm返回了一个list,把各种结果都装到z这个list里去了,然后给它命名了"lm"(这里还涉及到继承的概念,后面再说)

简单的总结下就是lm返回了一大堆结果,然后放到一个list里,然后取class"lm",当print的时候R调用print.lm只输出了其中部分结果。

到这里我再引用一个例子:
R>j <- list(name="Joe", salary=55000, union=T)<br />
R>class(j) <- "employee"<br />
R>attributes(j)<br />
$names<br />
[1] "name"   "salary" "union" </p>
<p>$class<br />
[1] "employee"</p>
<p>R>str(j)<br />
List of 3<br />
 $ name  : chr "Joe"<br />
 $ salary: num 55000<br />
 $ union : logi TRUE<br />
 - attr(*, "class")= chr "employee"<br />
R>j<br />
$name<br />
[1] "Joe"</p>
<p>$salary<br />
[1] 55000</p>
<p>$union<br />
[1] TRUE</p>
<p>attr(,"class")<br />
[1] "employee"<br />
R>print.employee <- function(wrkr) {<br />
+ cat(wrkr$name,"\n")<br />
+ cat("salary",wrkr$salary,"\n")<br />
+ cat("union member",wrkr$union,"\n")<br />
+ }<br />
R>j<br />
Joe<br />
salary 55000<br />
union member TRUE<br />
R>methods(,"employee")<br />
[1] print.employee<br />
R>j<br />
Joe<br />
salary 55000<br />
union member TRUE<br />
R>


大家应该知道了吧,最后讨论下继承:
R>k <- list(name="Kate", salary= 68000, union=F, hrsthismonth= 2)<br />
R>class(k) <- c("hrlyemployee","employee")<br />
R>k<br />
Kate<br />
salary 68000<br />
union member FALSE 


其实很简单,就是k有个子class,父class,R先找有没有符合第一个class的print.hrlyemployee,没有就调用print.employee
</p>

回复 第1楼 的 superdesolator:看好!学习!

好帖子,希望你一个一个函数慢慢写,范围就先限定在BASE包吧!

回复 第25楼 的 superdesolator:我估计这里的i应该是pi,但还是有些问题

35.关于loop的一点说明

由于R对数据的存取全是放在RAM里进行的(这些东西我也不太懂,以后大家看看数据结构和内存就慢慢能懂),

所以数据越大,越耗时,有的还出现超出内存范围之类的提示,这些我在这里不提,现在的也提不了。。。我只单就R神曲的相关部分说下:

最快的是冒号操作符

a=1:10


其次是事先设定长度:
n=10;a=numeric(n);<br />
for (i in 1:n) a[i]=i<br />


最慢的就是:
a=numeric(0);n=10;for( i in 1:n) a=c(a,i)


而遗憾的是,大多数新手和我都在问题比较复杂的时候用第3种,什么叫问题比较复杂的时候,见下例 :
R>my.df <- data.frame(a=character(0), b=numeric(0))<br />
R>for(i in 1:n) {<br />
+ this.N <- rpois(1, 10)<br />
+ my.df <- rbind(my.df, data.frame(a=sample(letters,<br />
+ this.N, replace=TRUE), b=runif(this.N)))<br />
+ }<br />
R>my.df<br />
   a           b<br />
1  t 0.434065103<br />
2  e 0.878656757<br />
3  y 0.536125700<br />
4  v 0.023334128<br />
5  q 0.669286852<br />


我们都习惯设置个量,初始化为0,或者NULL,然后不断的往里面,rbind或者cbind,这样做的坏处是,R先在内存中开辟了一段空间完成上面的事,但随着循环,发现开辟的地方不够用,所以就换地方,又循环又换,这样使得内存支离破碎,导致耗时费空间。这个时候,我们显然用不了:操作符了,所以我们只能追求第2快的方法:
R>my.list=vector('list',10);<br />
R>for(i in 1:10) {<br />
+ this.N=rpois(1,10)<br />
+ my.list[[i]]=data.frame(a=sample(letters,this.N,replace=TRUE),b=runif(this.N))<br />
+ }<br />
R>my.df=do.call('rbind',my.list)<br />
R>my.df<br />
    a           b<br />
1   v 0.779693265<br />
2   d 0.985035263<br />
3   m 0.516778964<br />
4   s 0.911832643<br />


这个方法快在哪?这就需要大家深入了解vector(),do.call(),并且我隐约感觉到这2个函数在以后的大家的编程中是需要采取这种模式的,因为它实现了第2快的方法,简单来说,这次它不像上次的代码,来一个存一个,现在就是开辟好一个地方,存向量,然后给向量每个值赋值(这里和简单情况下,n=10;for (i in n) a=i,几乎是一样的意思,只不过这里向量的每个分量不是numeric,而是list,大家可以试下,vector('numeric',10),体会一下),最后用do.call('rbind')我个人觉得太神奇了,太赞了.

最后有兴趣的同学可以改下下面3楼的代码,使得它变快:

http://cos.name/cn/topic/110372
</p>