74

使用 RI 时经常收到错误消息“下标越界”。例如

# 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

但是,我的问题不是关于这段特定的代码(即使它也有助于解决这个问题),但我的问题更笼统:

  • 下标越界错误的定义是什么?是什么原因造成的?
  • 有没有解决这种错误的通用方法?
4

7 回答 7

107

这是因为您尝试访问超出其边界的数组。

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

  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"
    

现在,我将看到变量的维度:

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])
于 2013-02-22T19:16:08.347 回答
4

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

于 2017-08-22T20:31:53.057 回答
4

如果这对任何人都有帮助,我在使用 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 中不存在,所以基本上我已经过滤掉了所有内容,并传递了一个空表来进行变异。 这个故事的寓意是您可能遇到数据问题而不是(只是)代码问题(因此您可能需要清理数据。)

感谢以上 agstudy 和 zx8754 对调试的帮助。

于 2019-01-23T19:03:20.597 回答
3

它只是意味着alter > ncol( reach_mat )or i > nrow( reach_mat ),换句话说,您的索引超出了数组边界(i 大于行数,或者 alter 大于列数)。

只需运行上述测试即可查看发生了什么以及何时发生。

于 2013-02-22T19:07:00.867 回答
2

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

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

输出是

[1] 1
[1] 0

而对于 python,例如

for i in range(x):
  print i

什么也没做。没有进入循环。

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

于 2013-02-22T19:19:50.843 回答
1

这来自斯坦福的 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计算,这里有一个错字

alter = this_node_reach[j] + 1

删除+1,它会正常工作

于 2013-03-05T14:23:32.167 回答
1

它对我的作用是回到代码中并检查错误或不确定的变化,并专注于需要拥有而不是美好拥有。

于 2021-03-11T07:59:53.190 回答