Подзаголовок вне границ - общее определение и решение?
При работе с 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
.
Однако мой вопрос заключается не в этом конкретном фрагменте кода (хотя было бы полезно также решить это), но мой вопрос более общий:
- Что такое определение ошибки подстрочного индекса? Что его вызывает?
- Существуют ли какие-либо общие способы приближения к такой ошибке?
Ответы
Ответ 1
Это потому, что вы пытаетесь получить доступ к массиву за его пределами.
Я покажу вам, как вы можете отлаживать такие ошибки.
- Я установил
options(error=recover)
-
Я запускаю 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")
-
Я ввожу 1 и получаю
Called from: top level
-
Я 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 выше за помощь в отладке.