Rプログラミング入門 10回目
この記事で、保存したcards.csvファイルをdeckオブジェクトに読み込んで
deckオブジェクトを操作する方法を学んでいきます。
mukkujohn.hatenablog.com
下準備
cards.csvファイルをロードしておきます
> deck <- read.csv("cards.csv") > head(deck) face suit value 1 king spades 13 2 queen spades 12 3 jack spades 11 4 ten spades 10 5 nine spades 9 6 eight spades 8
data.frameオブジェクトの要素の指定方法
data.frameから、要素を取得するには、deck[ , ]の様に記載します。
deckオブジェクトの1行、1列目の要素を取得しています。
> deck[1,1] [1] "king"
[]の添え字には、下記の6種類があります。
- 正の整数
- 負の整数
- ゼロ
- スペース
- 論理値
- 名前
1.正の整数
これはC#でいうところの配列の指定と同じですね。
ただ、Rはベクトルで指定できるところが違うため、その挙動も独特な印象です。
1行目、1列目を指しています。
> deck[1,1] [1] "king"
3行目、1列目から3列目を指しています。
> deck[3,c(1,2,3)] face suit value 3 jack spades 11
同じ次元(この例では行)に対して、同じ添え字(この例では"1")を指定すると
指定された次元を、指定された添え字分繰り返します。
> deck[c(1,1,1),c(1,2,3)] face suit value 1 king spades 13 1.1 king spades 13 1.2 king spades 13
2.負の整数
添え字に負の整数が指定できるなんて…。
負の整数を指定すると、その負の整数が指していない要素が返されます。
1行目以外全部を指しています。
> deck[-1,1:3] face suit value 2 queen spades 12 3 jack spades 11 4 ten spades 10 5 nine spades 9 … 50 three hearts 3 51 two hearts 2 52 ace hearts 1
逆に2行目から52行目以外全部 => 1行目のみ
> deck[-(2:52),1:3] face suit value 1 king spades 13
同じ次元に対して、正負混在の整数を指定するとエラーです。
> deck[c(-1,1),1] Error in xj[i] : only 0's may be mixed with negative subscripts
3.ZERO
添え字に0が利用できます。
Rでは、インデックスが1始まりなので、0が指定された際に特別な挙動をします。
C#は、インデックスは0始まりなのですが、Rを利用して統計している人には
リストのインデックスが0始まりなのは、気持ち悪いんでしょうね。
0を指定すると、指定された次元は何も返却しません。
> deck[0,0] 0 列 0 行のデータフレーム > deck[1,0] 0 列 1 行のデータフレーム > deck[0,1:3] [1] face suit value <0 行> (または長さ 0 の row.names)
どんな時に有効活用されるのか、今は分からないのですが、
いずれ指定する日が来るのでしょう。
4.スペース
スペースを指定すると、その次元の要素が全て返却されます。
つまるところ、記載する事を省略できますね。
列の指定を省略しています。2行目と全ての列の要素が返されます。
> deck[2, ] face suit value 2 queen spades 12
行の指定を省略しています。全ての行と1列目の要素が返されます。
> deck[ , 1] [1] "king" "queen" "jack" "ten" "nine" "eight" "seven" "six" "five" "four" [11] "three" "two" "ace" "king" "queen" "jack" "ten" "nine" "eight" "seven" [21] "six" "five" "four" "three" "two" "ace" "king" "queen" "jack" "ten" [31] "nine" "eight" "seven" "six" "five" "four" "three" "two" "ace" "king" [41] "queen" "jack" "ten" "nine" "eight" "seven" "six" "five" "four" "three" [51] "two" "ace"
5.論理値
TRUEが指定された行、または、列が返されます。
1行目から2行目で、1列目と3列目の要素が返されます。
> deck[1:2, c(TRUE,FALSE,TRUE)] face value 1 king 13 2 queen 12
当然、省略記法も使えます。
1行目で、2列目の要素が返されます。
> deck[1,c(F,T,F)] [1] "spades"
6.名前
オブジェクトが名前属性を持っている場合は、名前で抽出する事もできます。
1行目の、face列、suit列、value列が返されます。
> deck[1,c("face","suit","value")] face suit value 1 king spades 13
全ての行の、value列が返されます。
> deck[ ,c("value")] [1] 13 12 11 10 9 8 7 6 5 4 3 2 1 13 12 11 10 9 8 7 6 5 4 3 2 1 [27] 13 12 11 10 9 8 7 6 5 4 3 2 1 13 12 11 10 9 8 7 6 5 4 3 2 1
deckオブジェクトから、ランダムに、1個オブジェクトを取得する方法
deckオブジェクトには、52枚のカードの情報が割り当てられています。
> head(deck) face suit value 1 king spades 13 2 queen spades 12 3 jack spades 11 4 ten spades 10 5 nine spades 9 6 eight spades 8 > tail(deck) face suit value 47 six hearts 6 48 five hearts 5 49 four hearts 4 50 three hearts 3 51 two hearts 2 52 ace hearts 1
この52行ある要素の中から、1行ランダムに取得するには?
今まで行ってきた事から、sample()関数を利用すればできそうです。
52行をランダムに並び替えるshuffle関数です。
shuffle <- function(cards){ random <- sample(1:52, size = 52) cards[random, ] }
1行目の要素を返すdeal関数です。
deal <- function(cards){ cards[1, ] }
このshuffle関数とdeal関数を利用すると、
ランダムに並び替えられた52行あるdata.frame要素から
最初の1行の要素を返すことができます。
> deck2 <- shuffle(deck) > deal(deck2) face suit value 9 five spades 5
> deck2 <- shuffle(deck) > deal(deck2) face suit value 41 queen hearts 12
$記法と[[]]記法
$記法について
data.frameとlistのオブジェクトは、$を使う事で要素を取得できます。
コマンドは、data.frame$列名です。
deckオブジェクトのvalue列の取得
> deck$value [1] 13 12 11 10 9 8 7 6 5 4 3 2 1 13 12 11 10 9 8 7 6 5 4 3 2 1 [27] 13 12 11 10 9 8 7 6 5 4 3 2 1 13 12 11 10 9 8 7 6 5 4 3 2 1
deckオブジェクトのface列の取得
> deck$face [1] "king" "queen" "jack" "ten" "nine" "eight" "seven" "six" "five" "four" [11] "three" "two" "ace" "king" "queen" "jack" "ten" "nine" "eight" "seven" [21] "six" "five" "four" "three" "two" "ace" "king" "queen" "jack" "ten" [31] "nine" "eight" "seven" "six" "five" "four" "three" "two" "ace" "king" [41] "queen" "jack" "ten" "nine" "eight" "seven" "six" "five" "four" "three" [51] "two" "ace"
listオブジェクトにも試してみます。
> lst <- list(numbers = c(1,2), logical = TRUE, strings = c("a","b","c")) > lst $numbers [1] 1 2 $logical [1] TRUE $strings [1] "a" "b" "c" > lst$numbers [1] 1 2
ここで、ひとつ注意点があります。
lst[1]とlst$numbersでは、返されるオブジェクトのclassが異なります。
> class(lst[1]) [1] "list" > class(lst$numbers) [1] "numeric"
lst[1]はlistクラス、lst$numbersはnumericクラスです。
なので、こんな記載をするとエラーになります。
> sum(lst[1]) Error in sum(lst[1]) : invalid 'type' (list) of argument > sum(lst$numbers) [1] 3
そのため、要素の指定は、添え字なのか名前なのか意識して使い分けが必要です。
[[]]記法について
名前が分からない場合は[[]]が利用できます。
> lst[[1]] [1] 1 2
lstオブジェクトの1番目のオブジェクトに含まれる要素を取得しています。
(lst[1]と記載すると、lstオブジェクトの1番目のオブジェクトを取得します。)
これは、名前を指定して返却された要素と同じclassです。
> class(lst[[1]]) [1] "numeric" > class(lst$numbers) [1] "numeric"
[]内は文字列を利用する事もできます。
> lst[["numbers"]] [1] 1 2
ややこしいのが、lst[""]とlst[[""]]が異なる点ですね。
> lst["numbers"] $numbers [1] 1 2 > lst[["numbers"]] [1] 1 2
なんとなしに想像はつきますが、一応classを確認してみます。
> class(lst["numbers"]) [1] "list" > class(lst[["numbers"]]) [1] "numeric"
添え字や名前を指定するlistクラスのオブジェクトが返されて
$記法や、[[]]記法で指定するlistクラスの中の要素オブジェクトが返される事に
注意が必要ですね。
今日はここまで。