Subscript out of bounds - general definition and solution?

histelheim picture histelheim · Feb 22, 2013 · Viewed 435.6k times · Source

When working with R I frequently get the error message "subscript out of bounds". For example:

# Load necessary libraries and data
library(igraph)
library(NetData)
data(kracknets, package = "NetData")

# Reduce dataset to nonzero edges
krack_full_nonzero_edges <- subset(krack_full_data_frame, (advice_tie > 0 | friendship_tie > 0 | reports_to_tie > 0))

# convert to graph data farme 
krack_full <- graph.data.frame(krack_full_nonzero_edges) 

# Set vertex attributes
for (i in V(krack_full)) {
    for (j in names(attributes)) {
        krack_full <- set.vertex.attribute(krack_full, j, index=i, attributes[i+1,j])
    }
}

# Calculate reachability for each vertix
reachability <- function(g, m) {
    reach_mat = matrix(nrow = vcount(g), 
                       ncol = vcount(g))
    for (i in 1:vcount(g)) {
        reach_mat[i,] = 0
        this_node_reach <- subcomponent(g, (i - 1), mode = m)

        for (j in 1:(length(this_node_reach))) {
            alter = this_node_reach[j] + 1
            reach_mat[i, alter] = 1
        }
    }
    return(reach_mat)
}

reach_full_in <- reachability(krack_full, 'in')
reach_full_in

This generates the following error Error in reach_mat[i, alter] = 1 : subscript out of bounds.

However, my question is not about this particular piece of code (even though it would be helpful to solve that too), but my question is more general:

  • What is the definition of a subscript-out-of-bounds error? What causes it?
  • Are there any generic ways of approaching this kind of error?

Answer

agstudy picture agstudy · Feb 22, 2013

This is because you try to access an array out of its boundary.

I will show you how you can debug such errors.

  1. I set options(error=recover)
  2. I run reach_full_in <- reachability(krack_full, 'in') I get :

    reach_full_in <- reachability(krack_full, 'in')
    Error in reach_mat[i, alter] = 1 : subscript out of bounds
    Enter a frame number, or 0 to exit   
    1: reachability(krack_full, "in")
    
  3. I enter 1 and I get

     Called from: top level 
    
  4. I type ls() to see my current variables

      1] "*tmp*"           "alter"           "g"               
         "i"               "j"                     "m"              
        "reach_mat"       "this_node_reach"
    

Now, I will see the dimensions of my variables :

Browse[1]> i
[1] 1
Browse[1]> j
[1] 21
Browse[1]> alter
[1] 22
Browse[1]> dim(reach_mat)
[1] 21 21

You see that alter is out of bounds. 22 > 21 . in the line :

  reach_mat[i, alter] = 1

To avoid such error, personally I do this :

  • Try to use applyxx function. They are safer than for
  • I use seq_along and not 1:n (1:0)
  • Try to think in a vectorized solution if you can to avoid mat[i,j] index access.

EDIT vectorize the solution

For example, here I see that you don't use the fact that set.vertex.attribute is vectorized.

You can replace:

# Set vertex attributes
for (i in V(krack_full)) {
    for (j in names(attributes)) {
        krack_full <- set.vertex.attribute(krack_full, j, index=i, attributes[i+1,j])
    }
}

by this:

##  set.vertex.attribute is vectorized!
##  no need to loop over vertex!
for (attr in names(attributes))
      krack_full <<- set.vertex.attribute(krack_full, 
                                             attr, value = attributes[,attr])