Подтвердить что ты не робот

Подзаголовок вне границ - общее определение и решение?

При работе с R я часто получаю сообщение об ошибке "индекс за пределами границ". Например:

# 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.

Однако мой вопрос заключается не в этом конкретном фрагменте кода (хотя было бы полезно также решить это), но мой вопрос более общий:

  • Что такое определение ошибки подстрочного индекса? Что его вызывает?
  • Существуют ли какие-либо общие способы приближения к такой ошибке?
4b9b3361

Ответ 1

Это потому, что вы пытаетесь получить доступ к массиву за его пределами.

Я покажу вам, как вы можете отлаживать такие ошибки.

  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

Вы видите, что изменение вне пределов. 22> 21. в соответствии:

  reach_mat[i, alter] = 1

Чтобы избежать такой ошибки, лично я делаю это:

  • Попробуйте использовать функцию applyxx. Они безопаснее, чем for
  • Я использую seq_along а не 1:n (1: 0)
  • Попытайтесь думать в векторизованном решении, если вы можете избежать доступа к mat[i,j] index.

РЕДАКТИРОВАТЬ векторизацию решения

Например, здесь я вижу, что вы не используете тот факт, что 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])

Ответ 2

Это просто означает, что либо alter > ncol( reach_mat ), либо i > nrow( reach_mat ), другими словами, ваши индексы превышают границы массива (i больше числа строк или alter больше, чем количество столбцов).

Просто выполните указанные выше тесты, чтобы узнать, что и когда происходит.

Ответ 3

Я иногда сталкиваюсь с той же проблемой. Я могу ответить только на свою вторую пулю, потому что я не такой эксперт в 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

Ответ 4

Это было сделано из бесплатного учебника 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.)

ok, поэтому, когда когда-либо используется igraph, первый roll/column равен 0, кроме 1, но матрица начинается с 1, поэтому для любого вычисления под графиком вам понадобится x-1, показанный на

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

но для альтернативного расчета здесь есть опечатка

alter = this_node_reach[j] + 1

удалить +1, и он будет работать нормально

Ответ 5

Только дополнение к приведенным выше ответам: возможность в таких случаях заключается в том, что вы вызываете объект, который по какой-то причине недоступен для вашего запроса. Например, вы можете подмножать имена строк или имена столбцов, и вы получите это сообщение об ошибке, когда ваша запрашиваемая строка или столбец больше не являются частью матрицы данных или кадра данных. Решение. Как короткая версия вышеприведенных ответов: вам нужно найти имя последней рабочей строки или имя столбца, а следующий вызываемый объект должен быть тем, который не может быть найден. Если вы запускаете параллельные коды типа "foreach", тогда вам нужно преобразовать свой код в цикл for, чтобы устранить его.

Ответ 6

Если это кому-нибудь поможет, я столкнулся с этим при использовании 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 выше за помощь в отладке.