リストの [ ] は要素そのものではなく部分リストを返す([[ ]] との違い)
リストに対して[ ]でアクセスすると、中身の値そのものではなく、その要素だけを含む部分リストが返ります。中身の値を直接取り出したい場合は[[ ]]を使う必要があります。
エラーメッセージの読み方
Error in scr[1] + scr[[2]] : non-numeric argument to binary operator
Error- エラー種別 — 実行中に発生しました
scr[1] + scr[[2]]- 発生箇所 — エラーの原因になった呼び出し
non-numeric argument to binary operator- 詳細メッセージ — 何が問題だったか
このエラーが出る典型パターン
パターン1
1 scr <- list(10, 20, 30) 2 total <- scr[1] + scr[[2]] ^ 3 cat(total, "\n")
scr[1]は要素そのものではなく部分リストを返すため、数値計算に使うとエラーになります。scr[[1]]なら中身の数値が取れます。
直し方: [1] を [[1]] にします。
パターン2
1 prc <- list(100, 250, 300) 2 sum2 <- prc[1] + prc[[3]] ^ 3 cat(sum2, "\n")
[ ]はリストの一部を切り出すだけで中身の数値にはなりません。[[ ]]に置き換える必要があります。
直し方: [1] を [[1]] にします。
パターン3
1 wgt <- list(5, 15, 25) 2 diff <- wgt[2] - wgt[[1]] ^ 3 cat(diff, "\n")
wgt[2]は要素1個のリストのままなので、引き算のような数値演算には使えません。
直し方: [2] を [[2]] にします。
パターン4
1 tmp <- list(18, 22, 30) 2 avg2 <- (tmp[1] + tmp[[2]]) / 2 ^ 3 cat(avg2, "\n")
平均を計算するには中身の数値が必要なので、[[ ]]で値そのものを取り出す必要があります。
直し方: [1] を [[1]] にします。
パターン5
1 pts <- list(7, 14, 21) 2 total2 <- pts[1] * pts[[3]] ^ 3 cat(total2, "\n")
[ ]と[[ ]]は見た目が似ていますが、返す型がまったく異なるため数値演算では区別が必須です。
直し方: [1] を [[1]] にします。
よくある誤解
「[ ]と[[ ]]はどちらも中身の値をそのまま返すはず」という思い込みは誤りです。[ ]はリストの一部を切り出す演算子で、返り値は常にリストのままです。値そのものを使う演算(数値の計算など)に渡すとエラーになります。
実務での勘所
この挙動は、リスト特有の例外ルールではありません。[は、対象がベクトルであれリストであれ、常に「元と同じ種類の入れ物」を返すという1つの一貫したルールに従っています。c(1, 2, 3)[1]がベクトルを返すのと同じように、リストに対する[も律儀にリストを返しているだけです。「[は常に元の入れ物の形を保つ、[[ ]]だけが中身を1つ取り出す特別な演算子」と理解するほうが、他の型との一貫性が見えて覚えやすくなります。