web-dev-qa-db-ja.com

下付き添字-一般的な定義と解決策?

Rを使用しているときに、「subscript out of bound」というエラーメッセージが頻繁に表示されます。

# 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が生成されます。

しかし、私の質問はこの特定のコードに関するものではありません(それを解決することも役立ちますが)が、私の質問はより一般的です:

  • 下付きの範囲外エラーの定義は何ですか?何が原因ですか?
  • この種のエラーにアプローチする一般的な方法はありますか?
45
histelheim

これは、境界外の配列にアクセスしようとするためです。

このようなエラーをデバッグする方法を示します。

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

これが誰かを助けるなら、私が書いた関数で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の上記の回答に感謝します。

3

つまり、alter > ncol( reach_mat )またはi > nrow( reach_mat )のいずれか、つまり、インデックスが配列の境界を超えていることを意味します(iは行数よりも大きいか、alterは列数よりも大きい)。

上記のテストを実行するだけで、いつ何が起こっているのかを確認できます。

3
January

私は時々同じ問題に遭遇します。私は他の言語と同じようにRの専門家ではないので、2番目の箇条書きにしか答えられません。標準の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ステートメントを持つ以外に、良い回避策はまだ見つかりません。

2
James Pringle

これは、standfordのsna freeチュートリアルに由来し、...

# 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を使用する場合、最初のロール/列は1以外の0ですが、マトリックスは1から始まるため、igraphでの計算にはx-1が必要です。

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

しかし、別の計算のために、ここにタイプミスがあります

alter = this_node_reach[j] + 1

+1を削除すると問題なく動作します

1
YangJ

上記の応答への追加のみ:このような場合、オブジェクトを呼び出している可能性があり、何らかの理由でクエリで使用できません。たとえば、行名または列名でサブセット化できますが、要求された行または列がデータマトリックスまたはデータフレームの一部ではなくなったときに、このエラーメッセージが表示されます。解決策:上記の応答の短いバージョンとして:最後の作業行名または列名を見つける必要があり、次に呼び出されるオブジェクトは見つからなかったものでなければなりません。 「foreach」のような並列コードを実行する場合、コードをforループに変換してトラブルシューティングを行う必要があります。

1
Farshad