2013-02-22 11 views
30

Podczas pracy z R często pojawia się komunikat o błędzie "indeks dolny". For example:Indeks dolny poza podpunktem - definicja ogólna i rozwiązanie?

# 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 

To generuje następujący błąd Error in reach_mat[i, alter] = 1 : subscript out of bounds.

Jednak moje pytanie nie jest o tym szczególnym kawałek kodu (choć byłoby pomocne rozwiązania, które też), ale moje pytanie jest bardziej ogólne:

  • Jaka jest definicja subscript- błąd out-of-bounds? Co to powoduje?
  • Czy istnieją ogólne sposoby podejścia do tego rodzaju błędów?
+2

@ styczeń ma to. Oznacza to, że próbujesz coś dostać, np. Kolumnę lub wiersz, który nie istnieje. Na przykład, powiedzmy, że twoja tabela ma 10 wierszy, a twoja funkcja próbuje wywołać wiersz 15. – Ben

+2

A dla każdego, kto zastanawia się nad tym SZCZEGÓLNYM fragmentem kodu (z laboratoriów analizy sieci McFarlanda), to dlatego, że igraph zmienił swój schemat indeksowania z 0- opiera się na 1, więc "(i-1)" w "podskładniku" powinno być po prostu "i". – Sophologist

Odpowiedz

56

Dzieje się tak, ponieważ próbujesz uzyskać dostęp do tablicy poza jego granicę. Pokażę ci, jak możesz debugować takie błędy.

  1. ustawić options(error=recover)
  2. biegnę reach_full_in <- reachability(krack_full, 'in') uzyskać:

    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. wejdę 1 i dostaję

    Called from: top level 
    
  4. wpisuję ls() aby zobaczyć moje bieżące zmienne

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

Teraz widzę moich wymiarów zmiennych:

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

Widać, że alter jest poza granicami. 22> 21. w linii:

reach_mat[i, alter] = 1 

Aby uniknąć takich błędów, osobiście mogę to zrobić:

  • spróbuje użyć applyxx funkcję. Są bezpieczniejsze niż dla
  • Używam seq_along i nie 1: n (1: 0)
  • Spróbuj pomyśleć w wektorze, jeśli możesz uniknąć dostępu do indeksu [i, j].

EDIT vectorize rozwiązanie

Na przykład tutaj widzę, że you'dont wykorzystują fakt, że set.vertex.attribute jest wektorowy. można wymienić:

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

przez to:

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

Myślę, że potrzebujesz najpierw opcji (error = function() dump.frames (to.file = TRUE)), aby mieć gdzieś logi błędów. –

+3

Bardzo przydatne, to narzędzie do debugowania.W moim przypadku pozwoliło mi to stwierdzić, że błąd "subscript out of bounds" najwyraźniej był spowodowany tym, że użyłem "współczynnika" zamiast znaku, aby uzyskać dostęp do kolumny macierzy według nazwy. 'as.character' rozwiązał mój problem. Dziwne jest to, że ten błędny kod jest częścią biblioteki, którą z powodzeniem stosowałem na podobnych danych. – bli

+0

@bli Być może używasz kilku nowych wersji niektórych pakietów, które nie mają więcej wsparcia. – agstudy

2

To po prostu oznacza, że ​​albo alter > ncol(reach_mat) lub i > nrow(reach_mat), innymi słowy, indeksy przekroczyć granicę array (i jest większa niż liczba wierszy, lub zmieniać jest większa niż liczba kolumn).

Wystarczy uruchomić powyższe testy, aby zobaczyć, co i kiedy się dzieje.

2

czasami spotkać ten sam problem. Mogę odpowiedzieć tylko na twoją drugą kulę, ponieważ nie jestem tak specjalistą w R jak ja w innych językach. Odkryłem, że standardowa pętla for ma pewne nieoczekiwane wyniki. Powiedzieć x = 0

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

Wyjście jest

[1] 1 
[1] 0 

Podczas gdy z pytona, na przykład

for i in range(x): 
    print i 

nic nie robi. Pętla nie została wprowadzona.

Spodziewałem się, że jeśli x = 0 to w R, pętla nie zostanie wprowadzona. Jednak 1:0 jest prawidłowym zakresem liczb. Jeszcze nie znalazłem dobrą obejście oprócz posiadania if oświadczenie owijając for pętlę

+2

Z tego powodu nie robisz 'for (i in 1: x)' dla x, które może wynosić zero (robi to, co powinno nadać definicje, to nie jest to, co masz nadzieję, że zrobi). Robisz 'for (seq_len (x))', aby uzyskać pożądane zachowanie. –

1

ta pochodziła z SNA Standford za darmo poradnik i stwierdza, że ​​...

# 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, więc jeśli kiedykolwiek użyjesz igraph, pierwsza rolka/kolumna ma 0 inne niż 1, ale macierz zaczyna się od 1, a zatem dla dowolnego obliczenia pod symbolem, potrzebujesz x-1, pokazanego na

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

ale za alter obliczeń, jest literówka tutaj

alter = this_node_reach[j] + 1

usunąć +1 i będzie działać alright

0

tylko dodatkiem do powyższych odpowiedzi: a w takich przypadkach istnieje możliwość wywoływania obiektu, który z jakiegoś powodu nie jest dostępny dla zapytania. Na przykład możesz podzbiorować według nazw rzędów lub nazw kolumn, a otrzymasz ten komunikat o błędzie, gdy żądany wiersz lub kolumna nie będzie już częścią matrycy danych lub ramki danych. Rozwiązanie: Jako krótką wersję powyższych odpowiedzi: musisz znaleźć ostatnią roboczą nazwę wiersza lub nazwę kolumny, a następny wywoływany obiekt powinien być tym, który nie może zostać znaleziony. Jeśli uruchamiasz kody równoległe, takie jak "foreach", musisz przekonwertować swój kod na pętlę for, aby móc go rozwiązać.

Powiązane problemy