如何用R中的函数替换循环

时间:2016-05-21 04:07:45

标签: r for-loop nested sapply

我想替换以下代码中的循环。

    Test<-function(j){
      card<-5
      #matrix s is to hold the results
      s <- matrix(rep(0,j*card),nrow=j,ncol=card,byrow=TRUE)

       # Loop1
       for (k in 1:j)
       { 
        #A vector should be drawn from another matrix, 
        #for simplicity, I define a vector "sol" to be modified in Loop2
        sol<-rep(1,card)
        #Given the vector "sol", select a vector position randomly 
        #for a given no. of times (i.e. steps), say 10.
        step<-10

            # Loop2 - Modify value in sol  
            for (i in seq_len(step))
            {
             #Draw a position
             r<-sample(seq_len(card),1)
             #Each position has specific probabilities for 
             #assignment of possible values, meaning p is related to
             #the position. 
             #For simplicity, just define the probabilities by random here.
             p<-runif(3,0,1)   # just create p for each step
             p<-p/sum(p)       #
             #Finally, draw a value for the selected position and
             #value of sol within this loop is kept changing.
             sol[r]<-sample(1:3,1,prob=p)
             }
        # keep the result in matrix s.
        s[k,]<-sol }
    return(s)}

给定输入向量

         [,1] [,2] [,3] [,4] [,5]
    [1,]    1    1    1    1    1

预计输出如下矩阵:

         [,1] [,2] [,3] [,4] [,5]
    [1,]    1    1    3    2    3
    [2,]    1    1    1    1    3
    [3,]    2    2    2    2    3
    [4,]    2    1    2    2    1
    [5,]    1    1    3    1    1

Loop2中的每个步骤都取决于概率向量,然后使用该概率向量来改变sol中的值。然后我尝试用sapply替换Loop2,如下所示:

    sapply(seq_len(steps), function(x){ 
      r<-runif(seq_len(card),1)
      sol[r]<-sample(1:3,1,prob=p) #Try to modify value in sol
     })
    s[k,]<-sol #Actually, no change in sol.

然而,sol中的值没有变化,保持所有1,即1,1,1,1,1。

如何将Loop2替换为其他应用系列或其他功能?

谢谢。

3 个答案:

答案 0 :(得分:0)

如果我理解你正在尝试实现的目标,那么你不需要apply()函数:

Test <- function(j) {
  card <- 5

  p<-runif(3,0,1)
  p<-p/sum(p)

  out <- matrix(sample(1:3, j*card, replace=T, prob=p), ncol=card, nrow=j)
  return(out)
}

Test(5)

     [,1] [,2] [,3] [,4] [,5]
[1,]    2    2    2    1    1
[2,]    1    2    3    2    2
[3,]    2    3    1    1    2
[4,]    1    2    1    2    1
[5,]    2    1    1    2    2

答案 1 :(得分:0)

为了重构此函数,请注意所有r <- sample(card,1)都是来自多项分布的独立绘制。这可以从循环中拉出来。

要注意的第二件事是,如果多项式绘制为零,则给定s[i,j]的{​​{1}}的条件分布为1,否则为r。 (如果重复选择单元格,则分布不会改变)。

将这两个事实放在一起,我们有:

sample(3,1,prob=runif(3))

答案 2 :(得分:0)

那是怎么回事:

test2 <- function(j) {

  card <- 5

  # Create a matrix where each of the j*card row is a p as defined in your original function.
  p <- matrix(runif(3*j*card), ncol=3)
  p <- t(apply(p, 1, function(x) x/sum(x)))

  # For each row of p, draw a single value at random
  draws <- apply(p, 1, function(x) sample(1:3, 1, prob=x))

  # Format the output as a j*card matrix
  out <- matrix(draws, ncol=card, byrow=TRUE)
  return(out)
}

如果test2()符合您的要求,它的速度比我机器上的Test()大约快300倍。