web-dev-qa-db-fra.com

Indice en dehors des limites - définition générale et solution?

Lorsque je travaille avec R, je reçois fréquemment le message d'erreur "Indice en dehors des limites". Par exemple :

# 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

Cela génère l'erreur suivante Error in reach_mat[i, alter] = 1 : subscript out of bounds.

Cependant, ma question ne concerne pas cet élément de code particulier (même s'il serait utile de résoudre ce problème également), mais ma question est plus générale:

  • Quelle est la définition d'une erreur d'index en dehors des limites? Quelles sont les causes?
  • Existe-t-il des méthodes génériques pour aborder ce type d'erreur?
45
histelheim

C'est parce que vous essayez d'accéder à un tableau en dehors de ses limites.

Je vais vous montrer comment vous pouvez déboguer de telles erreurs.

  1. J'ai mis options(error=recover)
  2. Je lance reach_full_in <- reachability(krack_full, 'in') je reçois:

    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. J'entre 1 et je reçois

     Called from: top level 
    
  4. Je tape ls() pour voir mes variables actuelles

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

Maintenant, je vais voir les dimensions de mes variables:

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

Vous voyez que le changement est hors limites. 22> 21. dans la ligne :

  reach_mat[i, alter] = 1

Pour éviter une telle erreur, personnellement je fais ceci:

  • Essayez d’utiliser la fonction applyxx. Ils sont plus sûrs que for
  • J'utilise seq_along et non 1:n (1: 0)
  • Essayez de penser à une solution vectorisée si vous pouvez éviter mat[i,j] accès à l'index.

EDIT vectoriser la solution

Par exemple, je vois ici que vous n'utilisez pas le fait que set.vertex.attribute est vectorisé.

Vous pouvez remplacer:

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

par ça:

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

Si cela aide quelqu'un, je rencontre ce problème en utilisant purr :: map () avec une fonction que j'ai écrite et qui ressemble à ceci:

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) 

Je recevais parfois cette erreur avec des échantillons, mais la plupart du temps, je ne le ferais pas. La racine du problème est que certains des états de la table base_locations (PR) n'existaient pas dans la table states_table. J'avais donc tout filtré et passé une table vide pour la muter. La morale de l'histoire est que vous pouvez avoir un problème de données et pas (juste) un problème de code (vous devrez donc peut-être nettoyer vos données.)

Merci pour les réponses de agstudy et zx8754 ci-dessus pour l'aide au débogage.

3
John Paul Cassil

Cela signifie simplement que alter > ncol( reach_mat ) ou i > nrow( reach_mat ), autrement dit, vos index dépassent la limite du tableau (i est supérieur au nombre de lignes ou alt est supérieur au nombre de colonnes).

Il suffit de lancer les tests ci-dessus pour voir ce qui se passe et à quel moment.

3
January

Je rencontre parfois le même problème. Je ne peux que répondre à votre deuxième point, car je ne suis pas aussi expert en R que d’autres langues. J'ai trouvé que la boucle standard for a des résultats inattendus. Dites x = 0

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

La sortie est

[1] 1
[1] 0

Alors qu'en python, par exemple

for i in range(x):
  print i

ne fait rien. La boucle n'est pas entrée.

Je m'attendais à ce que si x = 0 cela dans R, la boucle ne soit pas entrée. Cependant, 1:0 est une plage de nombres valide. Je n'ai pas encore trouvé de solution de contournement en plus d'avoir une instruction if enveloppant la boucle for

2
James Pringle

Cela vient du tutoriel gratuit sna de standford et dit que ...

# 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, donc quand vous utilisez igraph, le premier rouleau/colonne est 0 autre que 1, mais la matrice commence à 1, donc pour tout calcul sous igraph, vous aurez besoin de x-1, montré à

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

mais pour le calcul de l'alter, il y a une faute de frappe ici

alter = this_node_reach[j] + 1

supprimez +1 et cela fonctionnera bien

1
YangJ

Seulement un ajout aux réponses ci-dessus: dans de tels cas, une possibilité est que vous appeliez un objet et que, pour une raison quelconque, il ne soit pas disponible pour votre requête. Par exemple, vous pouvez sous-classer par noms de lignes ou de colonnes et vous recevrez ce message d'erreur lorsque la ligne ou la colonne demandée ne fait plus partie de la matrice de données ou du cadre de données. Solution: en tant que version abrégée des réponses ci-dessus: vous devez rechercher le dernier nom de ligne ou de colonne actif et le prochain objet appelé doit être celui qui n'a pas été trouvé. Si vous exécutez des codes parallèles tels que "foreach", vous devez convertir votre code en une boucle for pour pouvoir le résoudre.

1
Farshad