#author("2022-01-30T08:42:57+09:00","","") COLOR(red){SIZE(25){ベクトルに関する Tips 大全}} ベクトルに関する操作は、R をマスターする基本です。関連する Tips を脈絡なくできるだけ集めたいと思います。お気づきの正統派・裏技テクニックを お寄せください。一部重複はむしろ好ましいと思います。 // 日本語の最後の一文字が抜けているという珍しい欠陥があったので修正した 2003/08/02(通りすがり(^_^;)) #contents ~ // ////////////////////////////////////////////////////////////////// // ベクトル // ////////////////////////////////////////////////////////////////// *ベクトルの各要素についての演算 [#fe53e246] > x <- 1:10 # 以下の例で共通に使うオブジェクト > y <- 21:30 > z <- 101:105 **定数との四則演算 [#jeba6a26] > x+2 [1] 3 4 5 6 7 8 9 10 11 12 > x-2 [1] -1 0 1 2 3 4 5 6 7 8 > x*2 [1] 2 4 6 8 10 12 14 16 18 20 > x/2 [1] 0.5 1.0 1.5 2.0 2.5 3.0 3.5 4.0 4.5 5.0 **ベクトルの要素間の四則演算 [#p33bd561] > x+y [1] 22 24 26 28 30 32 34 36 38 40 > x-y [1] -20 -20 -20 -20 -20 -20 -20 -20 -20 -20 > x*y [1] 21 44 69 96 125 156 189 224 261 300 > x/y [1] 0.04761905 0.09090909 0.13043478 0.16666667 0.20000000 0.23076923 [7] 0.25925926 0.28571429 0.31034483 0.33333333 要素数が異なるときは,短い方が繰り返して使用される > x+z [1] 102 104 106 108 110 107 109 111 113 115 **ベクトルの要素への関数などの適用 [#had52966] > x^2 [1] 1 4 9 16 25 36 49 64 81 100 > 1/x [1] 1.0000000 0.5000000 0.3333333 0.2500000 0.2000000 0.1666667 0.1428571 [8] 0.1250000 0.1111111 0.1000000 > sqrt(x) [1] 1.000000 1.414214 1.732051 2.000000 2.236068 2.449490 2.645751 2.828427 [9] 3.000000 3.162278 **ベクトルの要素の取り出し [#f5072b8c] [ と ] の間には単一の添字だけでなく,添字のベクトル,負の整数のベクトル,論理型ベクトル,文字型ベクトルを書くことができ,それぞれ以下のような意味を持つ. ***正整数の添字ベクトル [#g541a805] [ と ] の間に添字のベクトルを書けば,いくつかの要素をまとめて取り出すことが出来る.添字として 0 だけを指定すると,元のベクトルと同じ型で長さが 0 のベクトルが返される.また,ベクトルの長さを越える添字を指定すると NA (もとのベクトルが文字型ベクトルの場合は "" ) が返される. ( x <- c(1,2,3,4,5,6,7,8,9) ) # x <- 1:9 でも良い [1] 1 2 3 4 5 6 7 8 9 x[2] [1] 2 x[2:5] # x[2], ..., x[5] を取り出す -> x[c(2,3,4,5)] でも良い [1] 2 3 4 5 添字のベクトルの中に同じ添字が何度現れてもそれは構わない.その場合は同じ要素が何度も取り出されることになる. ***負の整数の添字ベクトル [#f03c8ad1] 正整数の代わりに負の整数を添字にすると,その要素を取り除くことが出来る.また,正整数と負の整数を混在させることは出来ない. ( x <- c(1,2,3,4,5,6,7,8,9) ) # x <- 1:9 でも良い [1] 1 2 3 4 5 6 7 8 9 x[-2] # x[2] 以外を取り出す -> x[c(1,3,4,5,6,7,8,9)] と同じ [1] 1 3 4 5 6 7 8 9 x[-(2:5)] # x[2], ..., x[5] 以外を取り出す [1] 1 6 7 8 9 x[c(-1,-3)] # x[1] と x[3] 以外を取り出す [1] 2 4 5 6 7 8 9 x[-c(1,3)] # これも上と同じである (注意?)Mathematica や Maple を使われる方はこの点が異なるので注意 ***論理型ベクトル [#r87b2188] [ と ] の間に、同じ長さの論理型ベクトルを書けば TRUE の要素に対応した要素が抜き出される.このとき [ と ] の間の論理型ベクトルの長さが足りなければ巡回的に評価が繰り返され,ベクトルの長さが長すぎるときは,その部分の評価結果には NA が出力される. ( x <- c(1, 2, 3, 4, 5, 6) ) # x <- 1:6 でも良い [1] 1 2 3 4 5 6 x[c(FALSE, TRUE, TRUE, FALSE, FALSE, FALSE)] # 2番めと3番めの要素を取り出す [1] 2 3 x[c(F, T, F, T, F, T, F, T)] # 最後の T を評価する要素が x には無い [1] 2 4 6 NA ( y <- x%%3==0 ) [1] FALSE FALSE TRUE FALSE FALSE TRUE x[y] # 論理値ベクトル指定 : x[x%%3==0] [1] 3 6 x <- rnorm(10) # 10個の正規乱数を生成 x[0 < x] # 正の値を持つ要素を抽出 [1] 2.24322154 0.98568617 0.03433169 0.49952966 x[0 < x & x < 0.5] # 0 〜 0.5 の間の値を持つ要素を抽出 [1] 0.03433169 0.49952966 (1:length(x))[0 < x & x < 0.5] # 何番目の要素が条件を満たしているか which(0 < x & x < 0.5) でもよい [1] 9 20 ***文字型ベクトル [#rbabdee1] ここではベクトルの names 属性によって付けられた要素ラベルを利用して要素を取り出す方法を紹介する.すなわち,[ と ] の間に文字型ベクトルを指定することで指定されたラベルをもつ要素が抽出される. ( x <- c(1, 2, 3, 4, 5, 6) ) # x <- 1:6 でも良い [1] 1 2 3 4 5 6 names(x) <- c("A", "B", "c", "d", "E", "F") # 各要素にラベルを付ける x["A"] # ラベル A を持つ要素を取り出す A 1 x["a"] # ラベル a を持つ要素を取り出す <NA> NA # (大文字と小文字は区別される) x[c("B", "E")] # ラベル B, E を持つ要素を取り出す B E 2 5 *ベクトルの要素数を得る [#b9219708] > x <- c(1,2,3) > length( x ) [1] 3 *ベクトルの一部を取り出す [#d99862bd] > x <- c(1,2,3,4,5,6,7,8,9) # x <- 1:9 でも良い > x[2:5] # x[2], x[3], ..., x[5] を取り出す、x[c(2,3,4,5)] でも良い [1] 2 3 4 5 > x[-2:5] # x[2], x[3], ..., x[5] 以外を取り出す と思ってはいけない(原文のチョンボですね) 以下にエラー x[-2:5] : 負の添字と混在できるのは 0 という添字だけです 正しくは,以下のように > x[-(2:5)] [1] 1 6 7 8 9 > y <- x%%3==0 [1] FALSE FALSE TRUE FALSE FALSE TRUE FALSE FALSE TRUE > x[y] # 論理値ベクトル指定、x[x%%3==0] でもよい [1] 3 6 9 * ベクトルの先頭、末尾を取り出す(行列、データフレーム、関数にも適用可能) head(), tail() 関数 (2004.09.17) [#ka870793] > x <- 1:100 > head(x) # デフォルトでは最初の6要素 [1] 1 2 3 4 5 6 > head(x, n=10) [1] 1 2 3 4 5 6 7 8 9 10 > tail(x, n=10) # 最初の10要素 [1] 91 92 93 94 95 96 97 98 99 100 > tail(x) # デフォルトでは末尾の6要素 [1] 95 96 97 98 99 100 *ベクトルの一部を取り除く [#ydafbdde] x <- 1:9 > x[-2, -3, -5] # x[2], x[3], x[5] を取り除く これも,チョンボ,以下のようなエラーメッセージに見舞われる 以下にエラー x[-2, -3, -5] : 次元数が正しくありません 正しくは > x[c(-2, -3, -5)] [1] 1 4 6 7 8 9 > x[-c(2,3,5)] # こっちの方がよいかも [1] 1 4 6 7 8 9 * ベクトルの一部を置き換える replace() [#j5b44940] > x <- 1:10 > y <- c(2, 5, 10) > z <- c(12, 15, 20) > w <- replace(x, y, z) # x の y 中の添字に相当する箇所を z の要素で順に置き換える > w # x 自身が変更されるわけではない [1] 1 12 3 4 15 6 7 8 9 20 //2004-1-2(Fri)佐藤 下に説明するwhichと組み合わせると,いろいろ応用が利く。 > w <- replace(x, y, NA) # 上記zの代わりにNAで置き換える > w [1] 1 NA 3 4 NA 6 7 8 9 NA > replace(w,which(is.na(w)),0) # wの中のNAを0で置き換える [1] 1 0 3 4 0 6 7 8 9 0 *ベクトルに要素を挿入(付加)する append() [#l64d81b8] > x <- 1:5 > append(x, c(11, 12, 13), after=3) [1] 1 2 3 11 12 13 4 5 > append(x, c(91, 92)) # after のデフォルトは末尾 [1] 1 2 3 4 5 91 92 *ベクトルを系統的に置き換える ifelse() (2004.10.08) [#tf475c2b] > x <- c(0,1,1,0,0,1,1,0,1) # バイナリベクトル > ifelse(x==0, "black", "white") [1] "black" "white" "white" "black" "black" "white" "white" "black" "white" *ベクトルの要素がある条件を満たすような添字を取り出す [#i5d41299] > x <- runif(10) > y <- which(x < 0.5) # 0.5 未満以の値を持つ要素の添字を取り出す > y [1] 3 5 6 10 > x[y] # 0.5 未満以の値を持つ要素を取り出す、x[x < 0.5] と同じ [1] 0.40643515 0.26432576 0.35265039 0.08640936 > (1:length(x))[x < 0.5] # 同じことを少し複雑に行う [1] 3 5 6 10 COLOR(red){注意!} xにNAが入っているとx[x < 0.5] とx[which(x < 0.5)]は異なります。 > x <- c(-Inf, 1, 2, 3, NA, NaN, 5, 6, Inf) > x[x < 4] [1] -Inf 1 2 3 NA NA > x[which(x < 5)] [1] -Inf 1 2 3 > x[x == 4] [1] NA NA *(規則的な)ベクトルを作る [#x446c479] -COLOR(red){a:b} # a から始まり(b を越えない)公差 1 (または -1) の等差数列 -COLOR(red){a*b^(0:(n-1))} # a から始まり,公比 b の等比数列を n 個 -COLOR(red){seq(a, b, by = c)} # a から始まり(b を越えない)公差 c の等差数列 -COLOR(red){seq(a, b, length = n)} # a, b 間を n 等分する等差数列 -COLOR(red){seq(along = x)} # 1:length(x) -COLOR(red){rep(x, n)} # x を n 回繰り返したベクトル -COLOR(red){numeric(n)} # 0 を n 個並べたベクトル -COLOR(red){フィボナッチ数列} # 趣旨から外れるが > x <- runif(100) # 一様疑似乱数 100 個からなるベクトル(テスト用に便利) > 1:10 [1] 1 2 3 4 5 6 7 8 9 10 > 10:1 [1] 10 9 8 7 6 5 4 3 2 1 > (-1):5 [1] -1 0 1 2 3 4 5 > (-1):(-5) [1] -1 -2 -3 -4 -5 > 1.3:10 [1] 1.3 2.3 3.3 4.3 5.3 6.3 7.3 8.3 9.3 > (-1.3):10 [1] -1.3 -0.3 0.7 1.7 2.7 3.7 4.7 5.7 6.7 7.7 8.7 9.7 > (1:10)/10 [1] 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 > seq(0, 1, length = 11) # 0 と 1 の間を 11等分する等差数列 [1] 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 > seq(1, 9, by = 2) 公差 2 の等差数列 [1] 1 3 5 7 9 > seq(1, 9, by = pi) [1] 1.000000 4.141593 7.283185 > seq(1, 6, by = 3) [1] 1 4 > 2^(0:10) [1] 1 2 4 8 16 32 64 128 256 512 1024 > 3*2^(0:10) [1] 3 6 12 24 48 96 192 384 768 1536 3072 > 1.2^(0:6) [1] 1.000000 1.200000 1.440000 1.728000 2.073600 2.488320 2.985984 > seq(17) # 1:17 と同じ [1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 > x <- c("a", "b", "c", "d", "e", "f") > seq(along = x) # 1:length(x) [1] 1 2 3 4 5 6 > rep(0,10) [1] 0 0 0 0 0 0 0 0 0 0 > rep(1:2,10) [1] 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 > rep(1:10, each=10) # 各数字を10回ずつ繰り返す [1] 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 [26] 3 3 3 3 3 4 4 4 4 4 4 4 4 4 4 5 5 5 5 5 5 5 5 5 5 [51] 6 6 6 6 6 6 6 6 6 6 7 7 7 7 7 7 7 7 7 7 8 8 8 8 8 [76] 8 8 8 8 8 9 9 9 9 9 9 9 9 9 9 10 10 10 10 10 10 10 10 10 10 > x <- numeric(10) > x [1] 0 0 0 0 0 0 0 0 0 0 > ((1+sqrt(5))^(1:10) - (1-sqrt(5))^(1:10))/2^(1:10)/sqrt(5) % フィボナッチ数列 [1] 1 1 2 3 5 8 13 21 34 55 # (1:10) のところに必要な項数を書く > ((1+sqrt(5))^(5:8) - (1-sqrt(5))^(5:8))/2^(5:8)/sqrt(5) [1] 5 8 13 21 # もちろん3箇所も変えるのは嫌だから,普通は関数で書く *ベクトルの大小順並べ変え order(), rev() [#db727d37] > x <- c(2,4,3,1) > x [1] 2 4 3 1 > ox <- order(x) > ox [1] 4 1 3 2 > x[ox] [1] 1 2 3 4 対応を保って,片方の変数の順番に並べ替えるには > x <- c(3,2,5,1,4) > y <- c(5,3,2,4,1) > ox <- order(x) > x <- x[ox] > y <- y[ox] # y も ox を使って並べ替える > rbind(x, y) [,1] [,2] [,3] [,4] [,5] x 1 2 3 4 5 y 4 3 5 1 2 逆順に並べ変えるには > rox <- rev(order(x)) > rox [1] 2 3 1 4 > x[rox] [1] 4 3 2 1 単に以下のようにしても良い > x <- c(3, 2, 1, 5, 4) > rev(sort(x)) [1] 5 4 3 2 1 > sort(x, decreasing=TRUE) # あるいはこのように [1] 5 4 3 2 1 *長さの等しい二つのベクトル x,y を x の大小順にプロット: [#s9e9c97e] > oo <- order(x) > plot(x[oo], y[oo], type="l") *ベクトルの成分がある性質をもつような添字を取り出す [#j41fa07c] > x <- 12:1 > x [1] 12 11 10 9 8 7 6 5 4 3 2 1 > x[x > 5] [1] 12 11 10 9 8 7 6 > y <- (1:length(x))[x > 5] # y は x[i]>5 であるような添字のベクトル > y [1] 1 2 3 4 5 6 7 > x[y] [1] 12 11 10 9 8 7 6 *空のオブジェクトを作る <- NULL, <- numeric(0) [#tb6e426f] > x <- NULL # または x <- numeric(0) > x NULL # x は空のオブジェクト > x[3] <- 3 # x[1], x[2] 抜きで x[3] に値を代入 > x [1] NA NA 3 # x[1], x[2] はまだ不定 > x[1:2] <- c(1, 2) > x [1] 1 2 3 *ベクトルの外積 outer() [#lc46fe28] z <- outer(x, y, FUN="afun") は次元 c(dim(x), dim(y)) で、要素 z[i, j] が afun(x[i], y[j]) である行列になる。関数 afun は任意 ベクトルにタグ名があれば保存される。x%o%y は outer(x, y, FUN="*") の省略形 > x <- runif(3) > y <- 1:3 > outer(x, y, FUN="^") [,1] [,2] [,3] [1,] 0.56709640 0.321598331 0.1823772568 # [1,2] 成分は 0.56709640^2 [2,] 0.06480775 0.004200045 0.0002721955 [3,] 0.06183690 0.003823802 0.0002364520 > x <- 1:10 > outer(x, x) # 九九ではなくて,十十か(^_^;) x%o%x と同じこと [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [1,] 1 2 3 4 5 6 7 8 9 10 [2,] 2 4 6 8 10 12 14 16 18 20 [3,] 3 6 9 12 15 18 21 24 27 30 [4,] 4 8 12 16 20 24 28 32 36 40 [5,] 5 10 15 20 25 30 35 40 45 50 [6,] 6 12 18 24 30 36 42 48 54 60 [7,] 7 14 21 28 35 42 49 56 63 70 [8,] 8 16 24 32 40 48 56 64 72 80 [9,] 9 18 27 36 45 54 63 72 81 90 [10,] 10 20 30 40 50 60 70 80 90 100 *数値ベクトルの対話的入力 readline() [#w1d67b8e] readline 関数で指定プロンプトを提示し、対話的に文字列を入力(任意の分離記号を指定できる)。結果 Str は文字列 "10,20,30"。strsplit 関数で文字列リストに変換し、unlist 関数で文字列ベクトル化、as.numeric 関数で数値化する > Str <- readline("Enter x: ") Enter x: 10,20,30 > x <- as.numeric(unlist(strsplit(Str, ","))) > x [1] 10 20 30 # x は数値ベクトル c(10,20,30) scan を使うこともできる。デフォールトではタブ区切り。入力の終わりにリターンキーを空押しする > x <- scan("", sep=",") 1: 1,2,3,4,5 6: Read 5 items > x [1] 1 2 3 4 5 *ランダムサンプル、置換、ブートストラップ sample() [#nfb105b3] 長さ n の与えられたベクトルの要素から長さ m の部分ベクトルをランダムに取り出す > x <- 1:n # 1:n の代わりに単に n としても良い > sample(x, m, replace=TRUE) # 同じ要素が選ばれても良い > sample(x, m, replace=FALSE) # 同じ要素は選ばれ無い(既定動作) > sample(x) # 特に m=n とするとランダムな置換になる > sample(c(0, 1), 100, replace = TRUE) # 100個のベルヌーイ試行 オプションの確率ベクトルを与えると各要素が選ばれる確率を指定できる(デフォルトは等確率 1/n) > p <- runif(n); p <- p/sum(p) > sample(x, m, replace=TRUE, prob=p) *パターンを持つベクトルの生成 sequence() [#h138ee6f] ベクトル x に対し sequence(x) は seq(x[1]), seq(x[2]), ... をこの順に並べたベクトルを生成する > sequence(3:1) [1] 1 2 3 1 2 1 > sequence(1:3) [1] 1 1 2 1 2 3 > sequence((-1):1) [1] 1 0 -1 1 0 1 > sequence(c(3, 3, 2)) [1] 1 2 3 1 2 3 1 2 *ベクトルからある値に最も近い要素の添字を求める [#lf8e865a] > x <- rnorm(1000) # 1000個の正規乱数 > which(abs(x-1.1) == min(abs(x-1.1))) # 1.1 に最も近い値を持つ要素の添字、which.min(abs(x-1.1)) でもよい [1] 657 > x[which(abs(x-1.1) == min(abs(x-1.1)))] # 該当要素値 [1] 1.112788 * ベクトルをリストに変換 as.list() (2003.12.22) [#e8b20b4a] 数値リストは as.numeric() で数値ベクトルに戻る > x <- 1:3 > x [1] 1 2 3 > as.list(x) [[1]] [1] 1 [[2]] [1] 2 [[3]] [1] 3 > as.numeric(as.list(x)) [1] 1 2 3 > x <- c("I", "love", "R") > x [1] "I" "love" "R" > as.list(x) [[1]] [1] "I" [[2]] [1] "love" [[3]] [1] "R" * 文字列を含むベクトルから、文字列を無視して数値計算する [#n7926298] > x <- c(1,2,"apple","orange") > sum(x) sum(x) でエラー: 引数 'type' (character) が不正です #文字列ベクトルだから当然。 > y <- as.numeric(x) #numericに強制変換 警告メッセージ: 強制変換により NA が生成されました > y [1] 1 2 NA NA > sum(y, na.rm=TRUE ) #NAならば除く方法はある。 [1] 3 最初からclassがcharacterのベクトルは上記でよいが、データフレームの列から取り出したベクトルはclassがfactorのことが多く、as.numeric(as.character(df[,1])) などと一度characterにせねばならない。でないと数値そのものでなくそのレベルが計算される。 * NA を含む長さが同じ2つのベクトルで,対応する要素がともに NA ではない要素を抽出 [#e25c03bd] > x <- c(1, 2, NA, 3, 4, 5, NA) > y <- c(NA, 1, NA, NA, 2, NA, 4) > print(rbind(x, y)) [,1] [,2] [,3] [,4] [,5] [,6] [,7] x 1 2 NA 3 4 5 NA y NA 1 NA NA 2 NA 4 > OK < complete.cases(x, y) > x <- x[OK] > y <- y[OK] > print(rbind(x, y)) [,1] [,2] x 2 4 y 1 2 * 既存の関数の活用 [#e7411206] ** ベクトル x の要素を無作為に n 個取り出す sample [#s88898f2] x[order(runif(length(x)))][1:n] // とか よりは // x[sample(1:length(x), n)] // sample(x) //のことかな? sample(x, n) //ですね ** cumsum [#l14f06ed] > ox <- c(1, 4, 6, 3, 10) > x <- ox > for (i in 1:length(ox)) x[i] <- sum(ox[1:i])-ox[i]/2 > x [1] 0.5 3.0 8.0 12.5 19.0 よりは > x <- cumsum(ox)-ox/2 > x [1] 0.5 3.0 8.0 12.5 19.0