下标超出界限 - 一般定义和解决方案?

时间:2013-02-22 19:00:49

标签: r matrix sna

使用R时,我经常收到错误消息“下标越界”。 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

这会生成以下错误Error in reach_mat[i, alter] = 1 : subscript out of bounds

但是,我的问题不是关于这段特殊的代码(尽管解决这个问题也很有帮助),但我的问题更为笼统:

  • 下标 - 越界错误的定义是什么?是什么原因造成的?
  • 是否有任何通用方法来处理此类错误?

7 个答案:

答案 0 :(得分:70)

这是因为您尝试从其边界外访问数组。

我将向您展示如何调试此类错误。

  1. 我设置options(error=recover)
  2. 我跑reach_full_in <- reachability(krack_full, 'in') 我明白了:

    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. 我输入1然后我

     Called from: top level 
    
  4. 我输入ls()以查看我当前的变量

      1] "*tmp*"           "alter"           "g"               
         "i"               "j"                     "m"              
        "reach_mat"       "this_node_reach"
    
  5. 现在,我将看到变量的维度:

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

    你看到alter超出界限。 22> 21。在行:

      reach_mat[i, alter] = 1
    

    为了避免这样的错误,我个人这样做:

    • 尝试使用applyxx功能。它们比for
    • 更安全
    • 我使用的是seq_along而不是1:n(1:0)
    • 如果可以避免mat[i,j]索引访问,请尝试在矢量化解决方案中思考。

    编辑矢量化解决方案

    例如,我在这里看到你没有使用set.vertex.attribute被矢量化的事实。

    您可以替换:

    # 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])
        }
    }
    

    由此:

    ##  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])
    

答案 1 :(得分:3)

它只表示alter > ncol( reach_mat )i > nrow( reach_mat ),换句话说,您的索引超出数组边界(i大于行数,或者alter大于列数)

只需运行上述测试即可查看发生的情况和时间。

答案 2 :(得分:2)

我有时遇到同样的问题。我只能回答你的第二颗子弹,因为我不像其他语言那样专注于R。我发现标准for循环有一些意想不到的结果。说x = 0

for (i in 1:x) {
  print(i)
}

输出

[1] 1
[1] 0

而使用python,例如

for i in range(x):
  print i

什么都不做。未输入循环。

我预计,如果{,1}在R中,则不会输入循环。但是,x = 0是有效的数字范围。我还没有找到一个好的解决方法,除了包含1:0循环的if语句

答案 3 :(得分:2)

如果这对任何人都有帮助,我在将purr :: map()与我编写的函数一起使用时遇到了这样的情况:

find_nearby_shops <- function(base_account) {
   states_table %>% 
        filter(state == base_account$state) %>% 
        left_join(target_locations, by = c('border_states' = 'state')) %>% 
        mutate(x_latitude = base_account$latitude,
               x_longitude = base_account$longitude) %>% 
        mutate(dist_miles = geosphere::distHaversine(p1 = cbind(longitude, latitude), 
                                                     p2 = cbind(x_longitude, x_latitude))/1609.344)
}

nearby_shop_numbers <- base_locations %>% 
    split(f = base_locations$id) %>% 
    purrr::map_df(find_nearby_shops) 

有时候我会在样本中得到这个错误,但是大多数时候我不会。问题的根源是base_locations表(PR)中的某些状态不存在于states_table中,因此本质上我已经过滤掉了所有内容,并将一个空表传递给mutate。 故事的寓意是,您可能遇到数据问题,而没有(仅仅是)代码问题(因此您可能需要清理数据。)

感谢上面的agstudy和zx8754的答案,以帮助进行调试。

答案 4 :(得分:1)

这来自standford的sna免费教程 它声明......

# Reachability can only be computed on one vertex at a time. To # get graph-wide statistics, change the value of "vertex" # manually or write a for loop. (Remember that, unlike R objects, # igraph objects are numbered from 0.)

好吧,所以当使用igraph时,第一个滚动/列是0而不是1,但矩阵从1开始,因此对于igraph下的任何计算,你需要x-1,如

所示

this_node_reach <- subcomponent(g, (i - 1), mode = m)

但是对于改变计算,这里有一个拼写错误

alter = this_node_reach[j] + 1

删除+1,它将正常工作

答案 5 :(得分:1)

只有上述回复的补充:在这种情况下,您可能正在调用一个对象,由于某种原因,您的查询无法使用该对象。例如,您可以按行名称或列名进行子集,当您请求的行或列不再是数据矩阵或数据框的一部分时,您将收到此错误消息。 解决方案:作为上述响应的简短版本:您需要找到最后一个工作行名称或列名称,下一个调用对象应该是无法找到的对象。 如果你运行像“foreach”这样的并行代码,那么你需要将代码转换为for循环才能对其进行故障排除。

答案 6 :(得分:0)

它对我的影响是返回代码并检查错误或不确定的更改,并专注于需要而不是好的。