前回まででRMarkdownファイルの作り方を学習しているので,これ以降はRMarkdownファイルにR(もしくはpython)のコードを書いていくこと.
Rではこれまでの例のように単独の数値や文字列を扱うケースは極めて稀である.通常は複数の数値や文字列を1セットにして様々な処理を行っていく.そうした1セットにしたデータセットの最もシンプルなものがベクトル(1次元配列)である.
例えば,バスケットボールチームのStartingメンバー5名でフリースロー10本勝負をしたときの成績として以下のような成績が出たとする.
名前 | 点数 |
---|---|
赤木 | 7 |
桜木 | 4 |
三井 | 10 |
宮城 | 7 |
流川 | 9 |
この表には名前のデータセットと得点のデータセットがある.これらがそれぞれベクトルとなる.Rでそれぞれのベクトルを作成するにはc()
という関数を使う.c
はconcatenate(連結する)の頭文字である.
Starting <- c("赤木","桜木","三井","宮城","流川")
Score<- c(7, 4, 10, 7, 9)
print(Starting) #print()関数を使わず,Startingだけでもよい.
## [1] "赤木" "桜木" "三井" "宮城" "流川"
print(Score)
## [1] 7 4 10 7 9
c()
関数を使うと,複数のベクトルを1つのベクトルにまとめることもできる.以下では新たにReserveのメンバーを追加して,フルメンバーのベクトルを作成している.
Reserve <-c("小暮","潮崎","安田","石井","佐々岡","桑田")
Full <- c(Starting, Reserve)
print(Full)
## [1] "赤木" "桜木" "三井" "宮城" "流川" "小暮" "潮崎" "安田"
## [9] "石井" "佐々岡" "桑田"
データ上あまり意味はないが,文字列型のデータが収められたベクトルと数値型のデータが収められたベクトルをc()
で連結することもできる.この場合,数値型のデータが文字列型に自動的に型変換される.
hoge <- c(Score, Starting)
print(hoge) #Scoreのデータが文字列型として出力される.
## [1] "7" "4" "10" "7" "9" "赤木" "桜木" "三井" "宮城" "流川"
先ほど作成したScore
は単に数値だけが並ぶベクトルであるが,以下のように各数値に「名前」を付けることができる.このようなベクトルを名前付きベクトルと呼ぶ.
なお,通常の文字列の扱いでは""
で括らなければならないが,名前に対しては""
で括らずにそのまま書いてもよいし,""
で括ってもよい.
NamedScore <- c(赤木=7, 桜木=4, 三井=10, 宮城=7, 流川=9)
print(NamedScore)
## 赤木 桜木 三井 宮城 流川
## 7 4 10 7 9
NamedScore <- c("赤木"=7, "桜木"=4, "三井"=10, "宮城"=7, "流川"=9)
print(NamedScore)
## 赤木 桜木 三井 宮城 流川
## 7 4 10 7 9
名前を付けておくとベクトル内の個々のデータにアクセスする際に,インデックス番号だけでなく,名前でアクセスすることもできる.詳しくは個々のデータへのアクセスへ.
ベクトルオブジェクトの型はそのベクトルが内部に持つデータの型によって決まる.冒頭で作成したStarting
とScore
の型を調べると以下の通りとなる.
class(Starting)
## [1] "character"
class(Score)
## [1] "numeric"
ベクトルオブジェクトの内の個別のデータにアクセスする(取り出す)には[]
を使って取り出したいデータのインデックス番号を指定する.
Full[1]
## [1] "赤木"
Score[3]
## [1] 10
複数のデータを同時に取り出すには[]
の中へ,c()
を使って複数の番号を指定する.
Starting[c(3,5)]
## [1] "三井" "流川"
Score[c(3,5)]
## [1] 10 9
例えば2番目から5番目のデータを取り出したいという場合には,いちいちc(2,3,4,5)
と打つのは面倒である.
そういう場合にはシーケンス演算子:
を用いて以下のように書くことができる.
Starting[c(2,3,4,5)] #めんどくさい
## [1] "桜木" "三井" "宮城" "流川"
Starting[c(2:5)]
## [1] "桜木" "三井" "宮城" "流川"
通常の指定とシーケンス演算子での指定は併せて用いることもできる.
Starting[c(1,3,4,5)] #めんどくさい
## [1] "赤木" "三井" "宮城" "流川"
Starting[c(1,3:5)]
## [1] "赤木" "三井" "宮城" "流川"
名前付きベクトルの場合には,インデックス番号の代わりに名前を指定してもよい.
NamedScore[5]
## 流川
## 9
NamedScore["流川"]
## 流川
## 9
NamedScore[c(1,3,4)]
## 赤木 三井 宮城
## 7 10 7
NamedScore[c("赤木","三井","宮城")]
## 赤木 三井 宮城
## 7 10 7
名前付きベクトルの場合には上記の通りに名前とベクトル値がセットになって返されてくる.
あくまで数値だけが欲しいという場合には,unname()
関数を用いる.あるいは,要素が1つだけの場合には[[]]
というように角カッコを重ねることでもよい.ただし,[[]]
が使えるのは要素が1つの時だけであり,複数の要素に対して用いるとエラーとなる.
unname(NamedScore[5])
## [1] 9
unname(NamedScore[c(1,3,4)])
## [1] 7 10 7
unname(NamedScore[c("赤木","三井","宮城")])
## [1] 7 10 7
NamedScore[["流川"]]
## [1] 9
NamedScore[[c(1,3,4)]] #これはエラー
## Error in NamedScore[[c(1, 3, 4)]]: attempt to select more than one element in vectorIndex
NamedScore[[c("赤木","三井","宮城")]] #これもエラー
## Error in NamedScore[[c("赤木", "三井", "宮城")]]: attempt to select more than one element in vectorIndex
ベクトル内のデータへのアクセスと同じ要領で書き換えたいデータを指定し,代入演算子を使って値を与えればよい
Starting[1] <- "Akagi"
Starting
## [1] "Akagi" "桜木" "三井" "宮城" "流川"
同時に複数のものを書き換えることもできる.
Starting[c(1,2)] <- c("Akagi", "Sakuragi")
Starting
## [1] "Akagi" "Sakuragi" "三井" "宮城" "流川"
ベクトルに対して数値を使って演算をすると,ベクトル内のすべてのデータに対してその数値の演算が行われる.
Score + 10
## [1] 17 14 20 17 19
Score - 3
## [1] 4 1 7 4 6
Score * 2
## [1] 14 8 20 14 18
Score / 4
## [1] 1.75 1.00 2.50 1.75 2.25
Score ^ 2
## [1] 49 16 100 49 81
また名前付きベクトルの場合には,名前そのものは演算には影響せず,データだけに演算がされる.演算結果は名前付きベクトルが返ってくる.
NamedScore + 10
## 赤木 桜木 三井 宮城 流川
## 17 14 20 17 19
NamedScore - 3
## 赤木 桜木 三井 宮城 流川
## 4 1 7 4 6
NamedScore * 2
## 赤木 桜木 三井 宮城 流川
## 14 8 20 14 18
NamedScore / 4
## 赤木 桜木 三井 宮城 流川
## 1.75 1.00 2.50 1.75 2.25
NamedScore ^ 2
## 赤木 桜木 三井 宮城 流川
## 49 16 100 49 81
同じ長さのベクトルであればベクトル同士の掛け算ができる.
hoge <- c(3,5,0,2,1)
Score + hoge
## [1] 10 9 10 9 10
Score * hoge
## [1] 21 20 0 14 9
Score / hoge #3つ目の分母が0になるので,Infinity,つまり無限大を表すInfが表示される
## [1] 2.333333 0.800000 Inf 3.500000 9.000000
名前付きベクトルの場合も同様.
NamedScore + hoge
## 赤木 桜木 三井 宮城 流川
## 10 9 10 9 10
NamedScore * hoge
## 赤木 桜木 三井 宮城 流川
## 21 20 0 14 9
NamedScore / hoge
## 赤木 桜木 三井 宮城 流川
## 2.333333 0.800000 Inf 3.500000 9.000000
さらに名前付きベクトル同士を演算させた場合.
namedhoge<- c(A=3,B=5,C=0,D=2,E=1)
NamedScore + namedhoge
## 赤木 桜木 三井 宮城 流川
## 10 9 10 9 10
namedhoge + NamedScore
## A B C D E
## 10 9 10 9 10
hoge + NamedScore + namedhoge
## 赤木 桜木 三井 宮城 流川
## 13 14 10 11 11
このように名前付きベクトル同士を演算させた場合には,式の中で最初に出てくる名前付きベクトルの名前だけが出力に反映される.
演算するベクトルの長さが異なっているとWarningが出力される.興味深いことに,Errorではなく,あくまでWarningであって計算結果は出力される.長さが短い方が長い方に合わせて循環していく.また,長い方のベクトルの長さが短い方のベクトルの長さの整数倍の時には,Warningも表示されない.
hoge2 <- c(3,5,0,2,1,4,3)
Score + hoge2 # 長さが合ってないのでWarningが出てくる
## Warning in Score + hoge2:
## 長いオブジェクトの長さが短いオブジェクトの長さの倍数になっていません
## [1] 10 9 10 9 10 11 7
hoge3 <- c(3,5,0,2,1,4,3,3,4,4) # hoge3の長さがScoreの2倍になっているのでWarningはでない
Score + hoge3
## [1] 10 9 10 9 10 11 7 13 11 13
ベクトルの中に指定したデータが含まれているかどうかは==
を用いることでしらべられる.
以下の例ではStartingベクトルの中に「流川」が含まれているかどうかを調べている.
Starting== "流川"
## [1] FALSE FALSE FALSE FALSE TRUE
返り値として,ベクトルの各要素が検索値と一致しているかをFALSE,TRUEのいずれかで示したベクトルが返される. ちなみにこのようなFALSE, TRUEの2値を取る型を論理型と呼ぶ.
ベクトルに要素を追加したい場合には,追加されるベクトルと追加したい要素やベクトルをc()
で結び付けて,元のベクトルオブジェクトに格納すればよい.もちろん,元のベクトルではなく別のベクトルオブジェクトとして格納することもできる.
木暮
を追加してみよう.
print(Starting)
## [1] "Akagi" "Sakuragi" "三井" "宮城" "流川"
Starting <- c(Starting, "小暮")
print(Starting)
## [1] "Akagi" "Sakuragi" "三井" "宮城" "流川" "小暮"
さらに,リザーブメンバーも加えて,フルメンバのベクトルを作成する.
Reserve <- c("潮崎","安田","角田","石井","佐々岡","桑田")
Full <- c(Starting, Reserve)
print(Full)
## [1] "Akagi" "Sakuragi" "三井" "宮城" "流川" "小暮"
## [7] "潮崎" "安田" "角田" "石井" "佐々岡" "桑田"
実際には「追加」をしているのではなく,元のベクトルと新しいデータを結び付けた新しいベクトルを作成したうえで,元のオブジェクト(箱)に格納しているだけである. したがって,もし末尾ではなく,先頭に追加したり,途中に追加したければ,以下のようにすればよい.
Starting<-c("赤木", "桜木", "三井", "宮城", "流川") #一旦元に戻す
Starting<-c("木暮", Starting) #先頭に追加
print(Starting)
## [1] "木暮" "赤木" "桜木" "三井" "宮城" "流川"
Starting<-c("赤木", "桜木", "三井", "宮城", "流川") #一旦元に戻す
Starting<-c(Starting[1:3], "木暮", Starting[4:5]) #途中に追加
print(Starting)
## [1] "赤木" "桜木" "三井" "木暮" "宮城" "流川"
ベクトルから特定の要素を削除したい場合には,残したい要素だけを取り出し,それをもとのベクトルオブジェクトに格納すればよい(もちろん別のオブジェクトとして格納してもよい).
末尾に追加した木暮
を削除してみよう.6番目にある木暮
を削除するには以下のようにする.
Starting<-c("赤木", "桜木", "三井", "宮城", "流川") #一旦元に戻す
Starting <- c(Starting, "小暮")#木暮を追加
print(Starting) # 小暮が入っている
## [1] "赤木" "桜木" "三井" "宮城" "流川" "小暮"
Starting <- Starting[c(1:5)]
print(Starting) # 小暮が除外された
## [1] "赤木" "桜木" "三井" "宮城" "流川"
あるいは,以下のように-
をつけてインデックス番号を与えると,そのインデックスで指定されたデータが除外される.
print(Full)
## [1] "Akagi" "Sakuragi" "三井" "宮城" "流川" "小暮"
## [7] "潮崎" "安田" "角田" "石井" "佐々岡" "桑田"
Full<-Full[-3] #3番目の三井が除かれる
print(Full)
## [1] "Akagi" "Sakuragi" "宮城" "流川" "小暮" "潮崎"
## [7] "安田" "角田" "石井" "佐々岡" "桑田"
Full<-Full[c(-4,-6)] # 4番目の流川と6番目の潮崎が除かれる
print(Full)
## [1] "Akagi" "Sakuragi" "宮城" "小暮" "安田" "角田" "石井"
## [8] "佐々岡" "桑田"
ただし,除外と抽出を同時にはできない.
Full[c(1:5,-3)] #これはエラー.取り出しと除外を同時できない.
## Error in Full[c(1:5, -3)]: 負の添字と混在できるのは 0 という添字だけです
RMarkdownファイルを作成し,以下の課題についてRMarkdown上で実行させ,KnitによってHTML出力させよ.
a
,b
,
C
を作成し,それぞれの内容をprint()
を用いて出力させよ.
a
: 1,2,3,4,5b
: 6,7,8,9,10c
: 11,12,13,14,15a
とb
を足し合わせてオブジェクトd
とし,その内容をprint()
を用いて出力させよ.d
とc
を掛け合わせてオブジェクトe
とし,その内容をprint()
を用いて出力させよ.関東
と近畿
を作成し,それぞれの内容をprint()
を用いて出力させよ.
関東
: “東京”, “千葉”, “埼玉”, “神奈川”, “茨城”,
“栃木”, “群馬”近畿
: “大阪”, “京都”, “兵庫”, “奈良”, “和歌山”,
“滋賀”, “三重”関東
と近畿
を合わせて都市
とし,その内容をprint()
を用いて出力させよ.都市
から”東京”,
“大阪”だけを除外し,その内容をprint()
を用いて出力させよ.ベクトルはあくまで1次元配列であるが,通常,データセットは以下のように行と列を持った2次元配列(要するに表)になっている.
名前 | 背番号 | 点数 |
---|---|---|
赤木 | 4 | 7 |
桜木 | 10 | 4 |
三井 | 14 | 10 |
宮城 | 7 | 7 |
流川 | 11 | 9 |
このような表としてのデータを一まとめにして扱うのがデータフレームという型のオブジェクトである.
データフレームを作るには以下のようにdata.frame()
関数を用いる.
Shohoku <- data.frame(
name = c("赤木","桜木","三井","宮城","流川"),
number=c(4,10,13,7,11),
score= c(7,4,10,7,9)
)
Shohoku
## name number score
## 1 赤木 4 7
## 2 桜木 10 4
## 3 三井 13 10
## 4 宮城 7 7
## 5 流川 11 9
data.frame()
関数の中でname
,number
,score
の3つのベクトルが作られている.つまりデータフレームとは同じ長さのベクトルが複数まとまったものと捉えることができる.
data.frame()
の中で改行(Enter)を入れているが,改行は入れても入れなくても良い.console上で()
や""
,''
の中で改行を入れた場合,行頭が>
から+
にかわり,直近の(
や"
,'
の範囲(スコープと呼ぶ)が閉じられずに続いていることを示す.スコープ閉じられていない限りはどれだけEnterを押してもコマンドは実行されない.適切にこれらが閉じられた場合には,閉じられた行でEnterキーを押すとことで一連の入力が一つながりのコマンドとして実行される.
なお,データフレームにおいては,行のことをobs
(observation:観測の略),列のことをvarialbles
(変数の意味)と呼ぶ.これは行方向(縦方向)は観察・測定されたサンプルが並べられており,列方向(横方向)は測定項目・測定変数が並べられている,ということである.
データフレームの各列のベクトルにアクセスするには,$
もしくは[]
を使う.
Shohoku$name # ベクトルとして出力される
## [1] "赤木" "桜木" "三井" "宮城" "流川"
Shohoku["name"] # nameだけを含んだデータフレームとして出力される
## name
## 1 赤木
## 2 桜木
## 3 三井
## 4 宮城
## 5 流川
Shohoku[1] #[]を使う場合には列の番号を与えても良い
## name
## 1 赤木
## 2 桜木
## 3 三井
## 4 宮城
## 5 流川
両者の出力結果は一見似ているが,$
の方は指定した列をベクトルとして出力されるのに対して,[]
の方は指定した列だけを含んだデータフレームとして出力される.
それぞれの違いを確認するには,出力の型を確認すればよい.
class(Shohoku$name) # ベクトルなので,文字列型となる
## [1] "character"
class(Shohoku["name"])#データフレームなのでdata.frame型となる
## [1] "data.frame"
複数の列を同時に取り出す場合にはc()
関数を使って複数の列を指定してやる.
Shohoku[c("name","score")]
## name score
## 1 赤木 7
## 2 桜木 4
## 3 三井 10
## 4 宮城 7
## 5 流川 9
Shohoku[c(1,3)] #名前ではなく列番号で指定した場合
## name score
## 1 赤木 7
## 2 桜木 4
## 3 三井 10
## 4 宮城 7
## 5 流川 9
この場合の出力結果はdata.frame型となる.
列にアクセスするのと同じ要領で$
または[]
で列を指定し,代入演算子によって書き換えたいベクトルを与えてやる.以下では$
で指定する方法で名前をローマ字に書き換えた後,[]
で指定する方法でローマ字になった名前を漢字に戻している.
Shohoku$name <- c("Akagi","Sakuragi","Mitsui","Miyagi","Rukawa")
Shohoku
## name number score
## 1 Akagi 4 7
## 2 Sakuragi 10 4
## 3 Mitsui 13 10
## 4 Miyagi 7 7
## 5 Rukawa 11 9
Shohoku[1] <- c("赤木","桜木","三井","宮城","流川")
Shohoku
## name number score
## 1 赤木 4 7
## 2 桜木 10 4
## 3 三井 13 10
## 4 宮城 7 7
## 5 流川 11 9
注意しないといけない点として,あくまで元の列ベクトルに含まれるデータ数(要するに行数)と同じデータ数のベクトルを与えなければならない.異なるデータ数のベクトルを与えた場合,Errorが返される.
Shohoku$name <- c("Akagi","Sakuragi","Mitsui","Miyagi") #データが1つ足りない
## Error in `$<-.data.frame`(`*tmp*`, name, value = c("Akagi", "Sakuragi", : 置換は 4 列ですが、データは 5 列です
Shohoku[1] <- c("Akagi","Sakuragi","Mitsui","Miyagi") #データが1つ足りない
## Error in `[<-.data.frame`(`*tmp*`, 1, value = c("Akagi", "Sakuragi", "Mitsui", : 置換は 4 列ですが、データは 5 列です
与えるベクトルデータが数値の場合には,演算を伴ったものでもよい.
Shohoku$score <- Shohoku$score + 5 # 5を足した
Shohoku
## name number score
## 1 赤木 4 12
## 2 桜木 10 9
## 3 三井 13 15
## 4 宮城 7 12
## 5 流川 11 14
Shohoku[3] <- Shohoku$score - 5 # 5を引いた
Shohoku
## name number score
## 1 赤木 4 7
## 2 桜木 10 4
## 3 三井 13 10
## 4 宮城 7 7
## 5 流川 11 9
Shohoku$score <- Shohoku$score * 3
Shohoku
## name number score
## 1 赤木 4 21
## 2 桜木 10 12
## 3 三井 13 30
## 4 宮城 7 21
## 5 流川 11 27
Shohoku[3] <- Shohoku$score / 3
Shohoku
## name number score
## 1 赤木 4 7
## 2 桜木 10 4
## 3 三井 13 10
## 4 宮城 7 7
## 5 流川 11 9
方法としては$
を使ってベクトルを取り出した上で[]
で取り出したい値のインデックス番号を指定する方法(これは要するにベクトルでの個々のデータへのアクセスと同じ)と,[]
を使って行番号と列番号を指定する方法とがある.
Shohoku$name[1]
## [1] "赤木"
Shohoku[1,1]
## [1] "赤木"
なお[行, 列]
である.
Shohoku[1,1]
## [1] "赤木"
Shohoku[1,2]
## [1] 4
Shohoku[1,3]
## [1] 7
列番号は以下のように,列名(ベクトル名)で指定しても良い.行については,番号でしか基本的にアクセスできない.
Shohoku[2,"name"]
## [1] "桜木"
Shohoku[2,"number"]
## [1] 10
Shohoku[2,"score"]
## [1] 4
Shohoku["桜木","score"] # これはNAが返される
## [1] NA
以下のように,ベクトル要素の検索機能を使って行の要素を使ったアクセスは可能であるが,これは5章で触れるデータフレームのフィルタリングを使う方が直観的である.
Shohoku[Shohoku$name=="桜木","score"]
## [1] 4
$
にせよ[]
にせよ,複数の要素を同時に取り出すことができる.
Shohoku$name[c(1,3,5)] # これは単純にベクトルとして取り出した後に[]でベクトル要素をしている
## [1] "赤木" "三井" "流川"
Shohoku[c(1,3,5),1] #これはデータフレームから行番号と列番号に合致するものを直接とりだしている
## [1] "赤木" "三井" "流川"
Shohoku[c(1,3,5),"name"] #列番号をベクトル名で指定した
## [1] "赤木" "三井" "流川"
[]
を使う場合で列を1つしか指定しなかった場合には上記のようにベクトルとしてデータが返される.一方,以下のように列を複数指定した場合には,データフレームとしてデータが返される.
Shohoku[c(1,3,5),c(1,3)] #複数の列(1,3列目)から複数の行番号(1,3,5行目)のデータを同時に取り出そうとしている.
## name score
## 1 赤木 7
## 3 三井 10
## 5 流川 9
Shohoku[c(1,3,5),c("name","score")]#列指定を名前にした
## name score
## 1 赤木 7
## 3 三井 10
## 5 流川 9
ベクトルの個々のデータの書き換えと同様に,それぞれの箇所にアクセスして代入演算子で書き換えてやる.以下では前と同様に$
で指定する方法で名前をローマ字に替えた後,[]
で指定する方法で名前を漢字に戻している
Shohoku$name[1] <- "Akagi"
Shohoku
## name number score
## 1 Akagi 4 7
## 2 桜木 10 4
## 3 三井 13 10
## 4 宮城 7 7
## 5 流川 11 9
Shohoku[1,1] <-"赤木"
Shohoku
## name number score
## 1 赤木 4 7
## 2 桜木 10 4
## 3 三井 13 10
## 4 宮城 7 7
## 5 流川 11 9
複数行を同時に書き換える場合には,ベクトルデータを与えてやる.
Shohoku$name[c(1,3,5)]<-c("Akagi","Mitsui","Rukawa")
Shohoku
## name number score
## 1 Akagi 4 7
## 2 桜木 10 4
## 3 Mitsui 13 10
## 4 宮城 7 7
## 5 Rukawa 11 9
Shohoku[c(1,3,5),1] <-c("赤木","三井","流川")
Shohoku
## name number score
## 1 赤木 4 7
## 2 桜木 10 4
## 3 三井 13 10
## 4 宮城 7 7
## 5 流川 11 9
複数行,複数列を同時に書き換えたい場合には,以下のようにdata.frame()
関数を使ってデータを与える.
# 赤木,三井,流川の名前をローマ字にするとともに,スコアを1にする
# name列とscore列は1列目と3列目にあるので,c(1,3)とインデックス番号で指定している
Shohoku[c(1,3,5),c(1,3)] <-data.frame(c("Akagi","Mitsui","Rukawa"),c(1,1,1))
Shohoku
## name number score
## 1 Akagi 4 1
## 2 桜木 10 4
## 3 Mitsui 13 1
## 4 宮城 7 7
## 5 Rukawa 11 1
# 赤木,三井,流川の名前を漢字に戻すとともに,スコアも戻す
# name列とscore列は列名で指定している
Shohoku[c(1,3,5),c("name","score")] <-data.frame(c("赤木","三井","流川"),c(7,10,9))
Shohoku
## name number score
## 1 赤木 4 7
## 2 桜木 10 4
## 3 三井 13 10
## 4 宮城 7 7
## 5 流川 11 9
既にあるデータフレームに新しい列(ベクトル)を追加したい場合には以下のように$
や[]
を用いて,新しい列名(ベクトル名)を指定して,その列に入れるデータをベクトルで与えるだけでよい.追加された列はデータフレームの末尾に入れられる.
Shohoku$Initial <- c("T.A.","H.S.","H.M.","R.M.","K.R.")
Shohoku
## name number score Initial
## 1 赤木 4 7 T.A.
## 2 桜木 10 4 H.S.
## 3 三井 13 10 H.M.
## 4 宮城 7 7 R.M.
## 5 流川 11 9 K.R.
Shohoku["Yomi"] <- c("あかぎたけのり","さくらぎはなみち","みついひさし","みやぎりょうた","るかわかえで")
Shohoku
## name number score Initial Yomi
## 1 赤木 4 7 T.A. あかぎたけのり
## 2 桜木 10 4 H.S. さくらぎはなみち
## 3 三井 13 10 H.M. みついひさし
## 4 宮城 7 7 R.M. みやぎりょうた
## 5 流川 11 9 K.R. るかわかえで
以下の例のように,[]
を使って複数の列を同時に追加することもできる.ただし,実用の場面では記述の分かりやすさの観点から,1つ1つ追加していく方が良い.
Shohoku[c("UnderName","Roman")] <-data.frame(
c("剛憲","花道","寿","亮太","楓"),
c("Akagi","Sakuragi","Mitsui","Miyagi","Rukawa")
)
Shohoku
## name number score Initial Yomi UnderName Roman
## 1 赤木 4 7 T.A. あかぎたけのり 剛憲 Akagi
## 2 桜木 10 4 H.S. さくらぎはなみち 花道 Sakuragi
## 3 三井 13 10 H.M. みついひさし 寿 Mitsui
## 4 宮城 7 7 R.M. みやぎりょうた 亮太 Miyagi
## 5 流川 11 9 K.R. るかわかえで 楓 Rukawa
Rの場合,それほど処理速度に敏感になる必要がないので,人から見た分かりやすさを重視した記述を心掛けるようにしよう.一方で,PythonやJavascript,あるいはC言語系などのプログラム言語を使って,動画像処理などリアルタイム性や高速な処理が求められるプログラムを記述する場合には,分かりやすさを犠牲にして,コンピュータ内部での計算処理回数の少ない書き方をすることもある.
列を削除する場合には,削除したい列にアクセスしてNULL
(ヌル)を代入すればよい.
Shohoku$Yomi <- NULL
Shohoku
## name number score Initial UnderName Roman
## 1 赤木 4 7 T.A. 剛憲 Akagi
## 2 桜木 10 4 H.S. 花道 Sakuragi
## 3 三井 13 10 H.M. 寿 Mitsui
## 4 宮城 7 7 R.M. 亮太 Miyagi
## 5 流川 11 9 K.R. 楓 Rukawa
Shohoku["Initial"] <- NULL
Shohoku
## name number score UnderName Roman
## 1 赤木 4 7 剛憲 Akagi
## 2 桜木 10 4 花道 Sakuragi
## 3 三井 13 10 寿 Mitsui
## 4 宮城 7 7 亮太 Miyagi
## 5 流川 11 9 楓 Rukawa
Shohoku[c("UnderName","Roman")] <- data.frame(NULL,NULL)
Shohoku
## name number score
## 1 赤木 4 7
## 2 桜木 10 4
## 3 三井 13 10
## 4 宮城 7 7
## 5 流川 11 9
データフレームへの行の追加にはrbind()
関数を使う.以下では同じ列名を持ったkogureというデータフレームを作成し,Shouhokuに追加している.
kogure <- data.frame(name="木暮", number=5, score=6)
Shohoku <- rbind(Shohoku , kogure)
Shohoku
## name number score
## 1 赤木 4 7
## 2 桜木 10 4
## 3 三井 13 10
## 4 宮城 7 7
## 5 流川 11 9
## 6 木暮 5 6
さらに,複数の行を同時に追加する場合には,複数行をもったデータフレームを作成してrbind()
で追加する.
Reserve <- data.frame(
name =c("潮崎","安田","角田","石井","佐々岡","桑田"),
number=c(8, 6, 9, 12, 13, 15),
score =c(6, 7, 7, 5, 5, 4)
)
Shohoku <-rbind(Shohoku, Reserve)
Shohoku
## name number score
## 1 赤木 4 7
## 2 桜木 10 4
## 3 三井 13 10
## 4 宮城 7 7
## 5 流川 11 9
## 6 木暮 5 6
## 7 潮崎 8 6
## 8 安田 6 7
## 9 角田 9 7
## 10 石井 12 5
## 11 佐々岡 13 5
## 12 桑田 15 4
列名が異なると以下の通りにエラーとなる.
Reserve2 <- data.frame(
name2 =c("潮崎","安田","角田","石井","佐々岡","桑田"),# nameがname2となっている
number=c(8, 6, 9, 12, 13, 15),
score =c(6, 7, 7, 5, 5, 4)
)
Shohoku <-rbind(Shohoku, Reserve2)
## Error in match.names(clabs, names(xi)): 名前が以前の名前と一致しません
Shohoku
## name number score
## 1 赤木 4 7
## 2 桜木 10 4
## 3 三井 13 10
## 4 宮城 7 7
## 5 流川 11 9
## 6 木暮 5 6
## 7 潮崎 8 6
## 8 安田 6 7
## 9 角田 9 7
## 10 石井 12 5
## 11 佐々岡 13 5
## 12 桑田 15 4
特定の行を削除したい場合には,以下のように削除したい行番号をベクトルで与えた上で-
をつけてやる.
Shohoku <- Shohoku[-c(6,7,8,9,10,11,12), ]
Shohoku
## name number score
## 1 赤木 4 7
## 2 桜木 10 4
## 3 三井 13 10
## 4 宮城 7 7
## 5 流川 11 9
注意すべき点として,行指定の後に,
をつけるのを忘れないようにすること.
もし,
をつけ忘れた場合,それは列ベクトルへのアクセスを意味するようになる.今回の場合だと列数は3つしかないので,以下の例のように特に何も起こらない.しかし,指定した列番号に対応するだけの列数があった場合には,それらの列が削除されたデータが返ってきてしまい,特にエラーにもならないので間違いに気づきにくくなる.
Shohoku <-rbind(Shohoku, Reserve)#一旦元のデータに戻す
Shohoku <- Shohoku[-c(6,7,8,9,10,11,12) ] # 行番号を指定した後,","をつけ忘れている
Shohoku
## name number score
## 1 赤木 4 7
## 2 桜木 10 4
## 3 三井 13 10
## 4 宮城 7 7
## 5 流川 11 9
## 6 潮崎 8 6
## 7 安田 6 7
## 8 角田 9 7
## 9 石井 12 5
## 10 佐々岡 13 5
## 11 桑田 15 4
なお,上記のように連続した番号を指定する場合に,一々すべての番号を記載するのは面倒である.このような場合には,:
(シーケンス演算子)を使って始端と終端を記述するとよい.
Shohoku
## name number score
## 1 赤木 4 7
## 2 桜木 10 4
## 3 三井 13 10
## 4 宮城 7 7
## 5 流川 11 9
## 6 潮崎 8 6
## 7 安田 6 7
## 8 角田 9 7
## 9 石井 12 5
## 10 佐々岡 13 5
## 11 桑田 15 4
Shohoku <- Shohoku[-c(6:12), ]
Shohoku
## name number score
## 1 赤木 4 7
## 2 桜木 10 4
## 3 三井 13 10
## 4 宮城 7 7
## 5 流川 11 9
今回のデータフレームには,name
のような文字列型やnumber
やscore
のような数値型など様々な型のベクトル(列)が含まれている.このような複数の型が混在するデータフレームに対しては演算処理を行うことはできない.演算処理を行いたい場合にはあくまで演算処理をしたい数値型の列のみを抜き出して,演算処理を行う.
Shohoku * 2 #これはエラー
## Error in FUN(left, right): 二項演算子の引数が数値ではありません
Shohoku$score*2 #これは数値型のベクトルなので演算処理が可能
## [1] 14 8 20 14 18
Shohoku$name *2 #これは文字列型のベクトルなのでエラー
## Error in Shohoku$name * 2: 二項演算子の引数が数値ではありません
Shohoku[c("number","score")] *2 #データフレーム型だが,両方とも数値型なので演算処理が可能
## number score
## 1 8 14
## 2 20 8
## 3 26 20
## 4 14 14
## 5 22 18
列名を把握したい(アクセスしたい)場合にはcolnames()
関数を用いる.
また,列名を変更したい場合には,colnames()
でアクセスした後に代入演算子を用いて,新しい列名を与えればよい.
colnames(Shohoku)
## [1] "name" "number" "score"
colnames(Shohoku) <- c("名前", "背番号", "得点")
Shohoku
## 名前 背番号 得点
## 1 赤木 4 7
## 2 桜木 10 4
## 3 三井 13 10
## 4 宮城 7 7
## 5 流川 11 9
colnames()
は列名をベクトルで返してくるので,[]
を用いてインデックス番号を指定してやることによって,個別の列名にアクセスしたり,個別の列名を変更することもできる.
Shohoku
## 名前 背番号 得点
## 1 赤木 4 7
## 2 桜木 10 4
## 3 三井 13 10
## 4 宮城 7 7
## 5 流川 11 9
colnames(Shohoku)[3] <- "score"
Shohoku
## 名前 背番号 score
## 1 赤木 4 7
## 2 桜木 10 4
## 3 三井 13 10
## 4 宮城 7 7
## 5 流川 11 9
自分で作れる程度のデータフレームであればあまり使うことは無いが,後で述べるように,外部のファイルからデータを読み込んだ場合には,そのファイルにどのような列が含まれているのかを把握したり,列名を変更したりするケースはよくある.
先の課題で作ったRMarkdownに追記する形で,以下の課題をRMarkdown上で実行させ,Knitでhtmlを出力させよ.
Kanto
を作成し,print()を用いて出力させよ.
都道府県名
: “東京”, “千葉”, “埼玉”, “神奈川”, “茨城”,
“栃木”, “群馬”県庁所在地
: “新宿”, “千葉”, “さいたま”, “横浜”,
“水戸”, “宇都宮”, “前橋”Kanto
に次の列を追加し,print()
を用いて出力させよ.
市外局番
: “03”, “043”, “048”, “045”, “029”, “028”,
“027”Kanto
から東京の行だけを取り出し,print()
を用いて出力させよ.Kanto
から埼玉と神奈川の行の市外局番だけを取り出し,print()
を用いて出力させよ.Kanto
の列名をPrefecture
,Capital
,AreaCode
に変更せよ.Kanto
から埼玉と神奈川の行を削除せよ.Kanto
からAreaCode
の列を削除せよ.実際の調査結果のデータを扱うときには,data.frameを毎度自分でちまちま作ってなんていられないので,表計算ソフトで作成されたデータファイルを読み込むことになる. 以下では 【test.csv】を用いるので,ファイル名をクリックしてダウンロードしておくこと.
Posit Cloudを利用している場合,Rにデータを読み込ませるには,データをPosit Cloudにアップロードする必要がある.
画面の右下のペインのFileというタブをクリックすると,現在のプロジェクトのフォルダ構成が表示される.
このタブの上部の「Upload」をクリックすると,ファイル選択画面が出てきて,データファイルを選択するとファイルがアップロードされる.
アップロードしたファイルはFileタブのリストに表示される(今回はtest.csvというファイルをアップロードした).
もっともシンプルな方法は表計算ソフトでデータファイルを保存する際にCSVというファイル形式で保存しておき,それをRで読み込む方法である.
CSVファイルとは,行ごとに要素が,
(コンマ)で区切られたファイル形式である.例えば,先ほどの表の
名前 | 背番号 | 点数 |
---|---|---|
赤木 | 4 | 7 |
桜木 | 10 | 4 |
三井 | 14 | 10 |
宮城 | 7 | 7 |
流川 | 11 | 9 |
の場合,CSVファイルでは以下のようになる.
名前, 背番号, 点数
赤木, 4, 7
桜木, 10,4
三井, 14,10
宮城, 7, 7
流川, 11, 9
CSVファイルを作るには,表計算ソフトでデータを作成(あるいは整理)したのち,保存の際にファイル形式をCSV
に指定すればよい(あるいは,Google
スプレッドシートの場合には,ファイル->ダウンロード->カンマ区切り形式(CSV)を選択すればよい.
csv
とはComma-Separated
Valuesの略で,日本語では「カンマ区切り形式」と訳される.
CSV形式のファイルをRで読み込む場合には,read.csv()
関数を使う.
1つ目のオプション(引数(ひきすう)と呼ぶ)ではダブルクォーテーションで括った上で読み込むファイル(既にPosit Cloudにアップロードしてある前提)を指定する.
2つ目の引数では,最初の行をヘッダー,つまり各列の名前として読み込むのか,最初の行をデータとして読み込むのかの指定である.TRUE
だとヘッダーとして読み込み,FALSE
だとデータとして読み込む.
3つ目の引数はファイルのエンコード形式を指定するもので,日本語のデータを読み込む場合には"UTF8"
を指定する.
以下の例では,test.csvというファイルを読み込み,その内容をmyData
というオブジェクトに格納している.
myData <- read.csv("test.csv", header = TRUE, fileEncoding = "UTF8")
myData
## 名前 背番号 点数
## 1 赤木 4 7
## 2 桜木 10 4
## 3 三井 14 10
## 4 宮城 7 7
## 5 流川 11 9
header=FALSE
だと以下の通りとなる.
myData <- read.csv("test.csv", header = FALSE, fileEncoding = "UTF8")
myData
## V1 V2 V3
## 1 名前 背番号 点数
## 2 赤木 4 7
## 3 桜木 10 4
## 4 三井 14 10
## 5 宮城 7 7
## 6 流川 11 9
それぞれの列名がV1
, V2
,
V3
となっており(自動的にそういう名前が割り当てられる),もともと列名としていた名前
,
背番号
,
点数
がデータの1行目に含められてしまっているのがわかる.
1行目をヘッダとして読むのか,データとして読むのかは読み込みたいファイルの中身に合わせて設定する.また,1行目をデータとして読み込んだ際には,自分で分かりやすい名前をcolnames()
関数を使って設定すること.
なお,ExcelでCSVファイルを作った場合には,上記のコマンドではうまく読まない場合がある.その場合には3つ目のfileEncodingのオプションを以下の通りに”SJIS”と指定する.(上のコマンドでうまく行っている場合には,逆に以下のコマンドだとエラーとなる)
myData <- read.csv("test.csv", header = TRUE, fileEncoding = "SJIS")
## Warning in read.table(file = file, header = header, sep = sep, quote = quote, :
## 入力コネクション 'test.csv' に不正な入力がありました
## Warning in read.table(file = file, header = header, sep = sep, quote = quote, :
## incomplete final line found by readTableHeader on 'test.csv'
myData
## 蜷榊燕 閭檎分蜿キ 轤ケ謨ー
## 1 襍、譛ィ 4 7
## 2 譯懈惠 10 4
## 3 荳我コ NA NA
Homeフォルダに別のフォルダを置いて,その中に読み込みたいファイルを置いている場合には,以下のように,フォルダ名を含めたファイル名を指定する.例えばHome
の下にPractice
というフォルダを置き,その中にtest.csv
を置いている場合には以下のように入力する.
myData <- read.csv("./Practice/test.csv", header = TRUE, fileEncoding = "UTF8")
Excelファイルを直接読み込みたい場合には,Posit Cloudに読み込みたいExcelファイルをアップロードしたうえで,RStudioのFileメニュー->Import Database ->From Excelを選択する.今回は【test.xlsx】を用いて実際にやってみる.
そのプロジェクト内で初めてExcelファイルを読み込む場合には,追加パッケージの読み込み確認の画面が出てくるが,そのまま「OK」をクリックすればよい. すると,パッケージの読み込みが暫く行われたのち,以下のようなウィンドウが表示される.
この画面の右上部の「Browse」ボタンをクリックすると,現在のプロジェクトにあるファイルリストが表示されるので,アップロードしておいたExcelファイルを選択する.すると,自動でファイルの中身が読み込まれ,プレビューが表示される.
このプレビューの下部にあるオプションを指定することによって,読み込みにあたっての細かな設定をする事が出来る.それぞれ,以下の通りである.
項目 | 内容 |
---|---|
Name | 読み込んだデータを格納するオブジェクトの名前の設定.デフォルトでは読み込んだファイル名がそのまま入力されている |
Sheet | Excelファイルのどのシートのデータを読むのかの設定 |
Range | 読み込む範囲の指定.エクセルの範囲表記の方法で記述する |
Max Rows | 読み込む最大行数の指定.データの行数よりも大きい数を指定した場合には無視される |
Skip | 読み込みをスキップする行数.指定した行数分だけデータの読み込みが飛ばされる.なお,ヘッダ部はカウントされない |
First Row as Names | 読み込むにあたって最初の行をヘッダ(列名)として読むのかデータとして読むのかの指定 |
Open Data Viewer | データの読み込みが終わったあと,自動的にデータ閲覧画面を開くかどうかの指定 |
以下の例では,オブジェクトの名前をmyDataに変更したものである.
右下部には,設定したオプションでExcelファイルを読み込むための関数一式(スクリプトと呼ぶ)が表示されている(このスクリプトは後で重要になるので,ここに表示されているということは覚えておこう).
この状態で「Import」を押すと,先ほど表示されていたスクリプトが実行され,以下の図のように読み込んだデータの閲覧画面が表示される.
また,以下のようにConcoleにmyData
と入力すると,console中にmyDataの中身が表示される.
myData # print(myData)でも可
## 蜷榊燕 閭檎分蜿キ 轤ケ謨ー
## 1 襍、譛ィ 4 7
## 2 譯懈惠 10 4
## 3 荳我コ NA NA
以上の処理は,GUIを使ってExcelデータを読み込む方法であったが,この方法の場合,Rを立ち上げ直したり,プロジェクトを再読み込みしたりすると,毎回GUIを使ってExcelファイルを読み込む必要がある.
スクリプトにExcelファイルを読みこむコードを記述しておけば,そのスクリプトを実行するだけで,Excelファイルを読み込むことができる.
そのための方法は,先ほどの「Excelファイルの読み込み画面の右下に表示されているCode Previewに記載されているスクリプトをコピーして,スクリプトエディタに貼り付けることである.
もっともシンプルなものとしては,以下のようなコードとなっているので,これをコピぺすればよ.
library(readxl)
myData <- read_excel("test.xlsx")
このスクリプトを実行することで,Excelファイルを読み込むことができる.
読み込むシートを変更したり,読み込む範囲を限定したり,あるいは先頭行をヘッダとして読み込むかどうかなどの設定は,read_excel()
関数のオプションで指定することもできるが,このあたりはExcelファイルの読み込み画面のGUI上で設定しておくと,その設定がCode
Previewに反映されるので,それをコピーすると良いだろう.
読み込んだデータはデータフレーム型となるため,データフレームの中で説明した方法で,以下のようにして各列にアクセスしたり,データを書き換えたり,列を追加したりできる.
myData <- read.csv("test.csv", header = TRUE, fileEncoding = "UTF8")
myData$名前
## [1] "赤木" "桜木" "三井" "宮城" "流川"
myData[1, "名前"] <- "Akagi"
myData
## 名前 背番号 点数
## 1 Akagi 4 7
## 2 桜木 10 4
## 3 三井 14 10
## 4 宮城 7 7
## 5 流川 11 9
myData$名前[1] <- "赤木"
myData
## 名前 背番号 点数
## 1 赤木 4 7
## 2 桜木 10 4
## 3 三井 14 10
## 4 宮城 7 7
## 5 流川 11 9
myData$Yomi <- c("あかぎ", "さくらぎ", "みつい", "みやぎ", "るかわ")
myData
## 名前 背番号 点数 Yomi
## 1 赤木 4 7 あかぎ
## 2 桜木 10 4 さくらぎ
## 3 三井 14 10 みつい
## 4 宮城 7 7 みやぎ
## 5 流川 11 9 るかわ
先の課題で作ったRMarkdownに追記する形で,以下の課題をRMarkdown上で実行し,Knit出力させよ.
次のファイルをダウンロードし,Posit Cloudに読み込ませたうえで,その読み込ませた内容を表示させよ.なお,読み込ませる際のオブジェクト名は任意のオブジェクト名として構わない.
また,読み込ませたデータのうち,ポジション
がDF
の選手の名前
と背番号
を取り出してprint()
で表示させよ.
c()
unname()
[](角カッコ)
:
-
$
rbind()
colnames()
data.frame()
rbind()
read.csv()