在R中填充子阵列[< -` * tmp *' :下标超出范围

时间:2017-09-30 07:37:36

标签: arrays r

我正在构建一个模拟,根据用户定义的参数随机为R中的子数组分配字符标签。

我的代码如下

K <- 2        ### Number of subarrays 
K1 <- c(1:3)  ### labels in first subarray
K2 <- c(4:5)  ### labels in second subarray

N <- 10 
Hstar <- 5 

perms <- 10  ### rows in each subarray

specs <- 1:N
specs1 <- 1:(N/2) ### specs in subarray 1
specs2 <- ((N/2) + 1):N ### specs in subarray 2

pop <- array(dim = c(c(perms, N/K), K)) ### population subarrays

haps <- as.character(1:Hstar) ### character labels

probs <- rep(1/Hstar, Hstar)  ### label probabilities


### 'for' loop to randomly populate 'pop' with 'haps' according to 'probs'

for(j in 1:perms){
    for(i in 1:K){
        if(i == 1){
            pop[j, specs, i] <- sample(haps, size = N, replace = TRUE, prob = probs)
    }
    else{
        pop[j, specs1,  1] <- sample(haps[K1], size = N/2, replace = TRUE, prob = probs[K1])
        pop[j, specs2,  2] <- sample(haps[K2], size = N/2, replace = TRUE, prob = probs[K2])    
    }
  }
}

我想要做的是填充(按行,而不是列)&#39; pops&#39;,它由两个子阵列组成,带有字符标签(&#39; haps&#39;)。具体地,子阵列1仅需要包含来自K1的标签,并且子阵列2必须仅包含来自K2的标签。 &#39;弹出&#39;尺寸为10×5×2(子阵列1中的值为50,子阵列2中的值为50)。不幸的是,R抛出了错误

Error in `[<-`(`*tmp*`, j, specs, i, value = c("4", "1", "3", "4", "1",  : 
subscript out of bounds

当嵌套&#39; for&#39;循环运行,我似乎无法理解为什么。我认为它与specs,specs1,specs2有关。基本上,来自&#39; specs&#39;的值。分为&#39; specs1&#39;和&#39; specs2&#39;。但是,错误表明问题在于pop [j,specs,i],但是由于K = 2,程序的这一部分不应该受到影响......但事实确实如此。

有关如何解决问题的任何想法,以便程序运行任何K值?

如果需要进一步澄清,请与我们联系。

2 个答案:

答案 0 :(得分:1)

让我划分零件上的错误。下面的行错误地指定了分配维度。 我注意到有一些不一致,因为你试图逐行循环(10次迭代),每行有5个元素(5列)。我怀疑你要按列循环,所以它应该是perms=5

为了描述这个问题,如果你按每个元素调试代码,你会看到pop[j, specs, i]。您正在尝试引用pop[ 1 , 1:10 , 1],并且您的子阵列具有维度10x5,这意味着您必须切换到pop[,1,1](您不需要指定1:10)就整个专栏而言。)

pop[j, specs, i] <- sample(haps, size = N, replace = TRUE, prob = probs)


sample(haps, size = N, replace = TRUE, prob = probs)
# [1] "3" "1" "4" "3" "2" "1" "1" "1" "2" "2"
pop[j, specs, i]
# Error in pop[j, specs, i] : subscript out of bounds
pop[specs, j, i]
# [1] "5" "2" "1" "4" "3" "5" "1" "5" "5" "2"

pop[, j, i] <- sample(haps, size = N, replace = TRUE, prob = probs)
#      [,1] [,2] [,3] [,4] [,5]
# [1,] "5"  NA   NA   NA   NA  
# [2,] "1"  NA   NA   NA   NA  
# [3,] "4"  NA   NA   NA   NA  
# [4,] "1"  NA   NA   NA   NA  
# [5,] "1"  NA   NA   NA   NA  
# [6,] "2"  NA   NA   NA   NA  
# [7,] "5"  NA   NA   NA   NA  
# [8,] "5"  NA   NA   NA   NA  
# [9,] "3"  NA   NA   NA   NA  
#[10,] "3"  NA   NA   NA   NA  

同样的问题出现在else部分,在那里我可以看到同样的错误。下面正确一个

pop[specs1 , j,  2] <- sample(haps[K1], size = N/2, replace = TRUE, prob = probs[K1])
pop[specs2 , j,  2] <- sample(haps[K2], size = N/2, replace = TRUE, prob = probs[K2])

无论如何,有更好的方法来完成这项任务:

pop[,,1] <- 
  apply(
    pop[,,1], 2, 
    function(x) sample(haps, size = N, replace = TRUE, prob = probs) )

pop[specs1,,2] <- 
  apply(
    pop[specs1,,2], 2, function(x)
     sample(haps[K1], size = N/2, replace = TRUE, prob = probs[K1]) )

pop[specs2,,2] <- 
  apply(
    pop[specs2,,2], 2, function(x)
      sample(haps[K2], size = N/2, replace = TRUE, prob = probs[K2]) )

答案 1 :(得分:0)

R语言在矢量化方面非常有效。您可以使用此功能来防止使用for循环。

为了使代码有效,我需要纠正一些错误:

  1. specs指的是数组的第一维而不是第二维。
  2. 我认为specs1specs2是指第二个子阵列(在您的示例中为i=2)。我修改了以后。
  3. 要填充数组,我会生成与您要填充的数组对应的大小样本。我使用了lengthdim。数组由列填充,即第一列,每行,第二列等......


    K <- 2        ### Number of subarrays 
    K1 <- c(1:3)  ### labels in first subarray
    K2 <- c(4:5)  ### labels in second subarray
    
    N <- 10 
    Hstar <- 5 
    
    perms <- 10  ### rows in each subarray
    
    specs <- 1:N
    specs1 <- 1:(N/2) ### specs in subarray 1
    specs2 <- ((N/2) + 1):N ### specs in subarray 2
    
    pop <- array(dim = c(c(perms, N/K), K)) ### population subarrays
    haps <- as.character(1:Hstar) ### character labels
    probs <- rep(1/Hstar, Hstar)  ### label probabilities
    
    pop[specs, , 1] <- sample(haps, size = length(specs) * dim(pop)[2], replace = TRUE, prob = probs)
    pop[specs1, , 2] <- sample(haps[K1], size = length(specs1) * dim(pop)[2], replace = TRUE, prob = probs[K1])
    pop[specs2, , 2] <- sample(haps[K2], size = length(specs2) * dim(pop)[2], replace = TRUE, prob = probs[K2])
    
    pop
    #> , , 1
    #> 
    #>       [,1] [,2] [,3] [,4] [,5]
    #>  [1,] "4"  "3"  "2"  "3"  "2" 
    #>  [2,] "5"  "4"  "3"  "1"  "4" 
    #>  [3,] "1"  "3"  "4"  "3"  "5" 
    #>  [4,] "3"  "3"  "5"  "5"  "3" 
    #>  [5,] "2"  "4"  "3"  "4"  "4" 
    #>  [6,] "3"  "3"  "2"  "4"  "1" 
    #>  [7,] "5"  "1"  "4"  "4"  "1" 
    #>  [8,] "4"  "3"  "2"  "3"  "2" 
    #>  [9,] "3"  "2"  "3"  "3"  "1" 
    #> [10,] "3"  "4"  "1"  "4"  "2" 
    #> 
    #> , , 2
    #> 
    #>       [,1] [,2] [,3] [,4] [,5]
    #>  [1,] "3"  "3"  "2"  "1"  "3" 
    #>  [2,] "2"  "2"  "2"  "2"  "2" 
    #>  [3,] "2"  "2"  "2"  "2"  "1" 
    #>  [4,] "2"  "3"  "2"  "3"  "1" 
    #>  [5,] "1"  "2"  "2"  "3"  "2" 
    #>  [6,] "5"  "5"  "5"  "4"  "5" 
    #>  [7,] "4"  "5"  "4"  "5"  "5" 
    #>  [8,] "5"  "5"  "4"  "5"  "5" 
    #>  [9,] "4"  "5"  "5"  "4"  "4" 
    #> [10,] "5"  "4"  "5"  "5"  "4"
    

    我认为你建立在参数化的基础上允许使用任何K值。