2 Rのデータ構造
2.2 変数の型
変数には数値だけではなく、文字など様々なタイプの変数が存在します。
R には以下のような変数の型(タイプ)があります。
- numeric (数値型)
- character (文字列型)
- factor (因子型)
- logical (論理値型)
変数の中身を確認(表示)させるには、Console に変数名を入力してエンターを押します。
このページの例ではそのようにして変数の中身を表示させています。
Console ではなくスクリプトファイルにプログラムを書いて実行させた場合には、ただ変数名を書くだけではその変数の内容が Console に表示されることはありません。
スクリプトファイルを使う場合には print() 関数を使うと良いでしょう。例えば x という変数の内容をスクリプト実行時にコンソールに出力(表示)したい場合には、print(x) とスクリプトファイルに書いておきます。
あるいは Environment タブに使用中の変数の一覧があるのでそこを見ても良いでしょう。
2.2.1 数値型
数値型 (numeric) は実数値のデータのことです。
R では、複数の数値が並んだデータ(ベクトル、後述)を作るにはc()を使います。
ベクトルに足し算引き算掛け算割り算をすればベクトル内の各要素に対して一度に計算を行えます。
2.2.2 文字列型
文字列型 (character) は文字データを表現するのに使います。
文字を引用符で囲うことで作成します。
引用符で囲えば数字でも文字列型になります。
文字列として日本語を使うこともできます。
2.2.3 因子型
因子型 (factor) はカテゴリカルなデータを扱うときなどに使われます。
例えば男性を1, 女性を2として入力されたデータがあったとします。
この時点ではxは数値型のベクトルですが、as.factor 関数を使うことでこれを因子型の配列に変換できます。
因子型のデータは順序情報を持つことができます。
各水準に順序関係がある場合はordered = Tを追加することでそれを明示できます。
また、その順序はデフォルトではアルファベット順になりますが、levelsを使って任意の順序を指定することができます。
x = c("Bad", "Good", "Excellent")
x = factor(x, ordered = T)
x
## [1] Bad Good Excellent
## Levels: Bad < Excellent < Good
# 因子の順序はABC順になる
x = c("Bad", "Good", "Excellent")
x = factor(x, ordered = T, levels = c("Bad", "Good", "Excellent"))
x
## [1] Bad Good Excellent
## Levels: Bad < Good < Excellent
# 順序を指定したい時は levels 引数を使う
x = c("Bad", "Good", "Excellent")
x = factor(x, levels = c("Bad", "Good", "Excellent"))
x
## [1] Bad Good Excellent
## Levels: Bad Good Excellent
# 順序づけはしないが、グラフなどで表示する際の順番は指定したい時は levels 引数を使う上記の3つ目の例ではorderedは使わずにlevelsだけを指定しています。グラフでどの因子から順に表示するかを指定したい場合などにこのようなことを行います。
2.2.4 論理値型
論理値型 (logical) は真(TRUE)か偽(FALSE)のどちらかの値のみをとるデータです。
TRUEとFALSEの代わりにTとFと書くこともできます。
以下の x と y は全く同じデータを意味します。
TRUE と FALSE はすべて大文字で書く必要があります。また、"で囲ってはいけません。
True と書くと変数名として扱われるし、“TRUE” と書くと文字列として扱われます。
論理値型は比較演算子を用いた際の結果の値にも使われる。
上記の例の>や==などは比較演算子と呼ばれる。
Rで用いられる比較演算子には以下のようなものがある。
| 演算子 | 構文 | 意味 |
|---|---|---|
| > | x > y | xはyより大きいか |
| >= | x >= y | xはy以上か |
| < | x < y | xはyより小さいか |
| <= | x >= y | xはy以下か |
| == | x == y | xとyは等しいか |
| != | x != y | xとyは等しくないか |
| %in% | x %in% y | xはyに含まれるか |
以下は具体例。
x = 3
y = 5
y >= x
## [1] TRUE
x <= 1
## [1] FALSE
x == 3
## [1] TRUE
x == 3.0
## [1] TRUE
3 == 6/2
## [1] TRUE
"AAA" == "X"
## [1] FALSE
"AAA" != "X"
## [1] TRUE
a = 5
b = c(3, 4, 5, 6, 7)
a %in% b
## [1] TRUE
x = c("Bad", "Good", "Excellent")
x = factor(x, ordered = T, levels = c("Bad", "Good", "Excellent"))
x[1] < x[2]
## [1] TRUE2.2.5 その他のデータ型
ここでは省略しますが、他にも以下のようなデータ型があります。
- Complex型(複素数を表現するのに使われる)
- Date型(日付や時刻を表現するのに使われる)
また、Numeric型にはさらにdouble型とinteger型に分けられます。
詳しくは以下のページを参照してください。
https://www.jaysong.net/RBook/datatype.html
2.2.6 データ型の判定
ある変数や配列がどのデータ型であるかは class 関数で調べることができます。
x = 1.0
class(x)
## [1] "numeric"
## 数値型です
x = c("a", "b", "c")
class( x )
## [1] "character"
## 文字列型です
x = as.factor(x)
class(x)
## [1] "factor"
## 因子型です
x = TRUE
class(x)
## [1] "logical"
## 論理値型ですある変数や配列が特定のデータ型であるかを判定する関数もあります。
たとえば、is.numeric() という関数は、数値型であるかどうかを判定します。
他のデータ型についてもisで始まる名前の関数が用意されています。
2.2.7 特殊な値について
NA
NA は欠損値を表現するために使われます。
たとえば以下の例では、ベクトル内の5つの値のうち、4番目の値が欠損値になっています。
このようなデータの具体的な状況としては、はいかいいえで回答する質問を5人に実施した際に、4番目の人の回答が収集できなかった、といったものが考えられます。
NA を含んでいても、変数のクラスはベクトル内の他の値のクラスのままです。
また、is.na() 関数で値がNAであるかを調べることができます。
NA を含んだ変数において問題になりやすいのが、平均や総和などの計算です。
以下の例では、数値ベクトルの平均値や総和の計算結果がNAになってしまっています。
na.rm = TRUEを関数に追加することで、NAを除去して数値部分だけを使って計算できます。
2.3 データ構造
Rには以下のようなデータ構造があります。
- vector (ベクトル)
- matrix (行列)
- array (配列)
- data frame (データフレーム)
- list (リスト)
- table (テーブル)
それぞれの性質は後ほど Table 2.2 に要約されます。
たくさん種類があって最初は複雑に思えるかもしれません。
この中でも最も重要なのがベクトルとデータフレームなので、まずはこの2つをよく理解しましょう。
2.3.1 Vector (ベクトル)
ベクトルの作成
ベクトルは1次元の配列で、数値や文字や論理値を要素として持つことができます。
c() という関数を使って作成できます。
a = c(-1, 0, 1, 2)
a
## [1] -1 0 1 2
b = c("Alice", "Bob", "Chen")
b
## [1] "Alice" "Bob" "Chen"
c = c(TRUE, TRUE, FALSE)
c
## [1] TRUE TRUE FALSEベクトル内の各要素は、全て同じ型の値になります。
上の例だと a は数値型の配列、b は文字型の配列、c は論理値型の配列です。
ベクトルに含まれる要素は、全て同じ型でなければなりません。
では、もし c() の中に違う型の値を混ぜるとどうなるでしょうか?
その場合、全ての要素が同じ型になるように、要素の値が勝手に変換されます。
a = c(0, TRUE, FALSE)
a
## [1] 0 1 0
## 全ての要素が数値型になっています
b = c(1, "A")
b
## [1] "1" "A"
## 全ての要素が文字列型になっています
c = c(2, TRUE, "A")
c
## [1] "2" "TRUE" "A"
## 全ての要素が文字列型になっていますa の場合、TRUE は 1 に、FALSE は 0 に置き換わっています。
数値と論理値を混ぜると、論理値は数値に置き換えられます。
b の場合、1 が “1” に置き換わっています。
置き換わった後の 1 は数値ではなく文字です。
ベクトルの要素の中に文字型の値がある場合、文字型以外の要素は全て文字型に変換されます。
c では3つ目の要素が文字型であるため、他の二つの要素は文字型に変換されます。
この場合は、TRUEは “1” ではなく “TRUE” という文字型の値になります。
なお、要素が1つだけのベクトルは Scalar (スカラー) とも呼ばれます。
(R ではスカラーは独立したデータ型ではなく、要素数が1つであるベクトルです)
以下の a と b は同じものになります。
コロン(:)を使うと値が連続する数値型ベクトルが作れます。
この場合、コロンの前後に最初の数値と終わりの数値を指定します。
ちなみに、以下の3つはどれも同じことです。
c() の中にベクトルを入れて、ベクトルを作ることもできます。
ベクトルの要素の操作
ベクトルが持つ要素を取り出すには角カッコ[]を使って以下のようにします。
a = c("a", "b", "c", "d", "e", "f")
# 1番目の要素を取り出す
a[1]
## [1] "a"
# 3番目の要素を取り出す
a[3]
## [1] "c"
# 1, 3, 5番目の要素を取り出す
a[c(1, 3, 5)]
## [1] "a" "c" "e"
# 2番目から4番目までの要素を取り出す
a[2:4]
## [1] "b" "c" "d"角カッコの中に1つの整数値を入れると、その番号番目の要素が取り出されます。
角カッコの中に書かれる数字のことをベクトルのインデックスと呼びます。
角カッコの中に整数値のベクトルを入れると、その番号に該当する全ての要素が取り出されます。
また、コロンを使うと連続する値を取り出す際に便利です。
また、以下のような方法でベクトル内の要素を書き換えることができます。
a = c("a", "b", "c", "d", "e", "f")
a
## [1] "a" "b" "c" "d" "e" "f"
a[1] = "1"
a
## [1] "1" "b" "c" "d" "e" "f"
a[c(2, 3)] = c("N2", "N3")
a
## [1] "1" "N2" "N3" "d" "e" "f"
a[4:6] = "X"
a
## [1] "1" "N2" "N3" "X" "X" "X"もし、存在しない位置の要素に値を代入するとどうなるでしょうか。
以下の例では、3つしか要素がないベクトル x に対して、7番目の要素に10という値を代入しています。
この場合、7番目の要素には10が正しく代入され、4〜6番目は NA という値で埋められます。
NA というのは欠損値を表現する際に使われる記号です。Not Available の頭文字に由来。
ベクトルに関する他の話題
ベクトルに関していくつかの補足説明をします。
まず、ベクトルの長さ(大きさ)を知る方法について。
ベクトルは一つ以上の要素を含むデータ構造です。あるベクトルにいくつの要素が含まれているのか知りたい場合には、length() 関数が利用できます。
次に、ベクトルを使った計算について。
ベクトルに数を足したり掛けたりした場合、ベクトルの全ての要素にその計算が行われます。
x = 1:5
x
## [1] 1 2 3 4 5
# x の全ての要素に2が足される
x + 2
## [1] 3 4 5 6 7
# x の全ての要素が3倍される
x * 3
## [1] 3 6 9 12 15これはたくさんの計算を同時に行うのに便利な性質です。
次の例では price という変数に様々な商品の値段を入れておき、消費税を掛けることで全ての商品の税込価格を計算しています。
price = c(300, 720, 450, 1200, 1500)
tax = 0.08
price * (1 + tax)
## [1] 324.0 777.6 486.0 1296.0 1620.0price の各要素が 1.08 倍されています。
次に、ベクトル同士での加減乗除について。
同じ長さのベクトル同士で計算をすると以下のような結果になります。
つまり、a と b の1番目の要素同士の計算、2番目の要素同士の計算、…というやり方で計算が行われます。
ベクトルのリサイクル
長さの異なるベクトル同士で計算をした場合、短い方のベクトルの内容が繰り返し(リサイクル)されて計算が行われます。
以下の例の場合、xは長さ7でyは長さ2です。この場合、yの内容がリピート(リサイクル)されて長さ7に合わせられ(c(1, 8, 1, 8, 1, 8, 1)になる)、そして計算が行われます。
ベクトルの要素名
使う機会はさほど多く無いかもしれませんが、ベクトルの各要素に名前を与えることが可能です。
# 4つの要素を持つデータ
x = c(10, 20, 5, 40)
# names() 関数を使って各要素に名前を与える
names(x) = c("north", "south", "east", "west")
# x には各要素に名前が付く
x
## north south east west
## 10 20 5 40
# 名前を使って要素にアクセスできる
x["east"]
## east
## 5
# 通常のようにインデックス番号を使うこともできる
x[3]
## east
## 5
# 名前を消したい場合は NULL を代入する
names(x) = NULL
x
## [1] 10 20 5 40
# 名前付きベクトルを作成する別の方法
y = c("Q1" = 4.5, "Q2" = 20.0, "Q3" = 50.1)
y
## Q1 Q2 Q3
## 4.5 20.0 50.1インデックス番号よりも名前で要素にアクセスした方が便利な場合などに有効です。
2.3.2 Data frame (データフレーム)
データフレームは R においてよく使われる重要なデータ構造です。
縦と横に数字や文字が並んだ下記の表のようなデータを表現するのに使えます。
エクセルなどからデータを R に読み込むとデータフレームになります。
データフレームは2次元のデータ構造である点では行列と似ています。
しかし、データフレームは列ごとに別の型のデータを持たせることが可能です。
例えば、以下のようなデータを作りたいとします。
(エクセルなどの外部データを取り込むのではなく R の中で手作業でデータを作るとします)
1,3列目は数値型、2,4列目は文字列型、5列目は論理値型です。
| id | name | age | gender | married |
|---|---|---|---|---|
| 1 | Alice | 10 | Female | FALSE |
| 2 | Bob | 15 | Male | FALSE |
| 3 | Charlotte | 20 | Female | FALSE |
| 4 | Dick | 35 | Male | TRUE |
まず各列のデータのベクトルを作成し、それらを data.frame() 関数の引数に並べてデータフレームを作ります。
id = 1:4
name = c("Alice", "Bob", "Charlotte", "Dick")
age = c(10, 15, 20, 35)
gender = c("Female", "Male", "Female", "Male")
married = c(FALSE, FALSE, FALSE, TRUE)
data = data.frame(id, name, age, gender, married, stringsAsFactors = F)
data
## id name age gender married
## 1 1 Alice 10 Female FALSE
## 2 2 Bob 15 Male FALSE
## 3 3 Charlotte 20 Female FALSE
## 4 4 Dick 35 Male TRUE
stringsAsFactors というのは、入力された文字列ベクトルを因子型に変換するかどうかの設定です。この例の場合はname列やgender列を文字列型のままにしておきたかったので FALSE にしています。
データフレームは同じ長さのベクトルを要素に持つリストです。各ベクトルは列とも呼ばれます。
上記の例のデータフレームは id, name, age, gender, married という5つの列を持っています。
データフレームの情報を調べるのに便利な関数を以下に示します。
# 列名
names(data)
## [1] "id" "name" "age" "gender" "married"
# 列数
ncol(data)
## [1] 5
# 行数
nrow(data)
## [1] 4また、head() 関数を使うとデータフレームの冒頭数行が表示されます。
データフレームの中身を簡単に確認したい際に便利です。
# データフレームの冒頭の6行分が表示される
# (このデータフレームは4行分しかデータがないので全ての行が表示されます)
head(data)
## id name age gender married
## 1 1 Alice 10 Female FALSE
## 2 2 Bob 15 Male FALSE
## 3 3 Charlotte 20 Female FALSE
## 4 4 Dick 35 Male TRUE
# 第二引数に数値を入れると何行分を表示させるか指定できる
head(data, 2)
## id name age gender married
## 1 1 Alice 10 Female FALSE
## 2 2 Bob 15 Male FALSEもうひとつ、str() 関数もデータフレームの概要を表示するのに便利です。
こちらの場合はベクトルの型も表示されます。
str(data)
## 'data.frame': 4 obs. of 5 variables:
## $ id : int 1 2 3 4
## $ name : chr "Alice" "Bob" "Charlotte" "Dick"
## $ age : num 10 15 20 35
## $ gender : chr "Female" "Male" "Female" "Male"
## $ married: logi FALSE FALSE FALSE TRUE2.3.2.1 データフレームの値を取り出す
データフレームの値を取り出す方法はいくつかあります。
1つは配列の場合と同じように、数値を使って取り出したい列や行の位置を指定することです。
## 2列目を取り出す
data[2]
## name
## 1 Alice
## 2 Bob
## 3 Charlotte
## 4 Dick
# 2,4列目を取り出す
data[c(2, 4)]
## name gender
## 1 Alice Female
## 2 Bob Male
## 3 Charlotte Female
## 4 Dick Male
## 2列目の3行目を取り出す
data[2, 3]
## [1] 15データフレームの各列には名前が付いているので、名前を使って列を指定することもできます。
## name列とage列を取り出す
data[c("name", "age")]
## name age
## 1 Alice 10
## 2 Bob 15
## 3 Charlotte 20
## 4 Dick 35また、列名を使う場合には $ 記号を使った方法があります。
この $ 記号を使った方法はデータフレームを扱う際にはよく使われます。
次のような指定方法も可能です。
指定した要素を別の値で置き換えることができます。
data$name[4] = "Donald"
data
## id name age gender married
## 1 1 Alice 10 Female FALSE
## 2 2 Bob 15 Male FALSE
## 3 3 Charlotte 20 Female FALSE
## 4 4 Donald 35 Male TRUE
data$age = c(1, 2, 3, 4)
data
## id name age gender married
## 1 1 Alice 1 Female FALSE
## 2 2 Bob 2 Male FALSE
## 3 3 Charlotte 3 Female FALSE
## 4 4 Donald 4 Male TRUE列に NULL を代入するとその列を削除できます。
2.3.3 Matrix (行列)
行列は2次元の配列です。
ベクトルと同様に、行列も全て同じ型の要素からなります。
行列は matrix() 関数を使って作成できます。
# 1から15までの数値ベクトルを、3行、5列の行列として作成
a = matrix(1:15, nrow = 3, ncol = 5)
a
## [,1] [,2] [,3] [,4] [,5]
## [1,] 1 4 7 10 13
## [2,] 2 5 8 11 14
## [3,] 3 6 9 12 15matrix() 関数の最初の引数にベクトルを入れます。
nrow と ncol で行(row)と列(column)の数を指定します。
また、byrow という引数を使うと、数値が並ぶ方向を切り替えることができます。
a = matrix(1:15, nrow = 3, ncol = 5, byrow = T)
a
## [,1] [,2] [,3] [,4] [,5]
## [1,] 1 2 3 4 5
## [2,] 6 7 8 9 10
## [3,] 11 12 13 14 15ベクトルではなくスカラーを指定した場合、全ての要素がその値である行列が作成されます。
dimnames という引数を使うと、行と列に名前を付けることができます。
v = 1:6
rnames = c("Cat1", "Cat2")
cnames = c("D1", "D2", "D3")
a = matrix(v, nrow = 2, ncol = 3, dimnames = list(rnames, cnames))
a
## D1 D2 D3
## Cat1 1 3 5
## Cat2 2 4 6行列の要素の操作は以下のように行うことができます。
a = matrix(1:15, nrow = 3, ncol = 5, byrow = T)
a
## [,1] [,2] [,3] [,4] [,5]
## [1,] 1 2 3 4 5
## [2,] 6 7 8 9 10
## [3,] 11 12 13 14 15
# 1行目の全ての要素を取り出す
a[1,]
## [1] 1 2 3 4 5
# 3列目の全ての要素を取り出す
a[, 3]
## [1] 3 8 13
# 2行目の2列目にある値を取り出す
a[2, 2]
## [1] 7
# 1行目の2,3列目の要素を取り出す
a[1, 2:3]
## [1] 2 3
# 1,3行目の1,5列目の要素を取り出す
a[c(1, 3), c(1, 5)]
## [,1] [,2]
## [1,] 1 5
## [2,] 11 15行や列に名前が付いている場合は名前を使って要素を取り出すこともできます。
v = 1:6
rnames = c("Cat1", "Cat2")
cnames = c("D1", "D2", "D3")
a = matrix(v, nrow = 2, ncol = 3, dimnames = list(rnames, cnames))
a
## D1 D2 D3
## Cat1 1 3 5
## Cat2 2 4 6
a["Cat1",]
## D1 D2 D3
## 1 3 5
a["Cat2", "D2"]
## [1] 4行列の要素の書き換えは以下のようです。
a = matrix(1:15, nrow = 3, ncol = 5, byrow = T)
a
## [,1] [,2] [,3] [,4] [,5]
## [1,] 1 2 3 4 5
## [2,] 6 7 8 9 10
## [3,] 11 12 13 14 15
a[1,] = 21:25
a
## [,1] [,2] [,3] [,4] [,5]
## [1,] 21 22 23 24 25
## [2,] 6 7 8 9 10
## [3,] 11 12 13 14 15
a[3,] = 0
a
## [,1] [,2] [,3] [,4] [,5]
## [1,] 21 22 23 24 25
## [2,] 6 7 8 9 10
## [3,] 0 0 0 0 0
a[2, 3] = 999
a
## [,1] [,2] [,3] [,4] [,5]
## [1,] 21 22 23 24 25
## [2,] 6 7 999 9 10
## [3,] 0 0 0 0 0
a[1:3, 2:3] = matrix(1, nrow = 3, ncol = 2)
a
## [,1] [,2] [,3] [,4] [,5]
## [1,] 21 1 1 24 25
## [2,] 6 1 1 9 10
## [3,] 0 1 1 0 02.3.4 Array (配列)
配列は行列と似ていますが、3次元以上の次元を持つことができます。
array() 関数を使って作成します。
a = array(1:24, dim = c(2, 4, 3))
a
## , , 1
##
## [,1] [,2] [,3] [,4]
## [1,] 1 3 5 7
## [2,] 2 4 6 8
##
## , , 2
##
## [,1] [,2] [,3] [,4]
## [1,] 9 11 13 15
## [2,] 10 12 14 16
##
## , , 3
##
## [,1] [,2] [,3] [,4]
## [1,] 17 19 21 23
## [2,] 18 20 22 24
a[2, 1, 2]
## [1] 10
a[1, 1:3, 1:2] = 0
a
## , , 1
##
## [,1] [,2] [,3] [,4]
## [1,] 0 0 0 7
## [2,] 2 4 6 8
##
## , , 2
##
## [,1] [,2] [,3] [,4]
## [1,] 0 0 0 15
## [2,] 10 12 14 16
##
## , , 3
##
## [,1] [,2] [,3] [,4]
## [1,] 17 19 21 23
## [2,] 18 20 22 242.3.5 List (リスト)
リストは、様々な種類のデータ(オブジェクト)を持つことができます。
以下の例では数値、文字列、配列を要素に持つリストを作成しています。
x = list(1:4, c("A", "B", "C"), matrix(1:8, ncol = 2))
x
## [[1]]
## [1] 1 2 3 4
##
## [[2]]
## [1] "A" "B" "C"
##
## [[3]]
## [,1] [,2]
## [1,] 1 5
## [2,] 2 6
## [3,] 3 7
## [4,] 4 8リストを作成する際に各要素に名前を付けることもできます。
x = list(num = 1:4, str = c("A", "B", "C"), arr = matrix(1:8, ncol = 2))
x
## $num
## [1] 1 2 3 4
##
## $str
## [1] "A" "B" "C"
##
## $arr
## [,1] [,2]
## [1,] 1 5
## [2,] 2 6
## [3,] 3 7
## [4,] 4 8リストの要素を取り出すには2重の各括弧 [[ ]] や $ 記号を使います。
2.4 データ構造のまとめ
データ構造を表にまとめます。
| データ構造 | 日本語名 | 次元 | データ型 |
|---|---|---|---|
| vector | ベクトル | 1次元 | 1種類 |
| matrix | 行列 | 2次元 | 1種類 |
| array | 配列 | 多次元 | 1種類 |
| data.frame | データフレーム | 2次元 | 複数種類 |
| list | リスト | - | 複数種類 |
| table | テーブル | 多次元 | int(整数値) |
ベクトル、行列、配列は1種類のデータ型を持ちます。
配列のうち、1次元の配列がベクトル、2次元の配列が行列です。
データフレームはベクトルを要素(列)に持つリストです。
2.5 確認問題
2.5.1 データ型
以下のコードを実行した際、変数 y のクラス(データ型)として正しいものはどれですか。
- logical (論理値型)
- character (文字列型)
- numeric (数値型)
- factor (因子型)
解答
解答は2。
x は論理値型の変数です。class() 関数は引数となる変数のデータ型を文字列として返すので、y は文字列型です。y には "character" という文字列型のデータが入っています。
2.5.2 ベクトルの型変換
c() 関数の中に異なる型のデータを混ぜてベクトルを作成しました。以下のコードを実行した結果、ベクトル x の各要素は最終的にどの型になりますか。
- すべて numeric (数値型) になる
- すべて character (文字列型) になる
- すべて logical (論理値型) になる
- 数値・文字列・論理値が混在する
解答
解答は2。
ベクトルに含まれる要素はすべて同じ型でなければなりません。文字列が含まれている場合、他の数値や論理値はすべて強制的に文字列型に変換されます。10 は "10" になり、TRUE は "TRUE" になります。
2.5.3 比較演算子の評価
以下のコードを実行した際、コンソールに表示される結果として正しいものはどれですか。
- TRUE
- FALSE
- 3
- NA
解答
解答は1。
%in% 演算子は、左側の値が右側のベクトルの中に含まれているかを判定します。3 は c(1, 3, 5) の中に含まれているため、TRUE が返されます。
2.5.4 ベクトルのリサイクル
長さが異なる2つのベクトル a と b の足し算を行いました。計算結果として正しいものはどれですか。
- 11 22 3 4
- 11 22 NA NA
- 11 22 13 24
- エラーが発生して計算できない
解答
解答は3。
R では長さの異なるベクトル同士で計算する場合、短い方のベクトルが長い方のベクトルの長さに合うように自動で値のリサイクル(繰り返し)が行われます。この例では変数 b が計算の前に 10, 20, 10, 20 というベクトルに変換され、その後、a との足し算が行われます。
2.5.5 特殊な値(NAとNULL)の性質
以下のベクトル x の要素数(長さ)を length(x) で調べた場合、結果はいくつになりますか。
- 3
- 4
- 5
- エラーになる
解答
解答は2。
NA(欠損値)は「値が欠けていること」を示す1つの要素としてカウントされますが、NULL は「値が存在しないこと」を示し、ベクトルの要素としては無視されます。そのため、要素は 1, 2, NA, 3 の4つとなります。実際、x という変数の中身を見ると 1 2 NA 3 となっています。
2.5.6 データ構造の分類
以下の特徴を持つデータ構造はどれですか。
- 2次元の構造(行と列)を持つ
- 列ごとに異なるデータ型(数値型、文字列型など)を持つことができる
- vector (ベクトル)
- matrix (行列)
- array (配列)
- data frame (データフレーム)
解答
解答は4。
行列(matrix)や配列(array)はすべての要素が同じ型でなければなりませんが、データフレームは列ごとに異なる型のベクトルを持つことができます。
2.5.7 ベクトルの作成と四則演算
c() 関数を使って、10, 20, 30 という3つの数値を持つベクトル x を作成してください。 その後、x のすべての要素から 5 を引いた結果を表示してください。
2.5.8 欠損値(NA)を含む計算処理
以下のように欠損値(NA)を含んだベクトル x があります。
x の平均値を計算してください。
解答
- NA が含まれるベクトルに対してそのまま mean(x) を実行すると結果も NA になってしまいます。引数に
na.rm = TRUEを追加することで、欠損値を除いた要素だけで計算できます。 - na.rm という引数は他の関数でもよく使うので、よく覚えておいてください。
- na.rm 引数を持つ関数の代表例を挙げておきます。これらの関数を使って計算結果が NA になった場合は、
na.rm = TRUEを追加し忘れていることが原因であることが多いです。 - sum() 要素の合計値
- prod() 要素の積
- median() 中央値
- min() 最小値
- max() 最大値
- range() 最小値と最大値
- sd() 標準偏差
- var() 分散
2.5.9 因子型(Factor)の変換と順序指定
以下のようなTシャツのサイズを表す文字列ベクトル x があります。
これを factor() 関数を使って因子型に変換してください。 その際、アルファベット順ではなく S < M < L という意味のある順序を持たせるために、levels 引数と ordered 引数を正しく指定してください。
2.5.10 行列(Matrix)の要素アクセス
以下のコードで、1から9までの数字が並んだ3行3列の行列 m を作成しました。
この行列から、「2行目のすべての値」を取り出すコードを書いてください。
2.5.11 データフレームの作成
以下の2つのベクトルがあります。
これらのベクトルを使って、name 列と age 列を持つデータフレーム df を作成してください。
解答
name = c("Alice", "Bob", "Charlie")
age = c(24, 30, 18)
df = data.frame(name, age)
print(df)
## name age
## 1 Alice 24
## 2 Bob 30
## 3 Charlie 18
# 方法2:直接データフレームの内容を記述する場合
df = data.frame(
name = c("Alice", "Bob", "Charlie"),
age = c(24, 30, 18)
)
- data.frame() 関数の引数にベクトルを渡すことで、それらを列として持つ表形式のデータ(データフレーム)を作成できます。
- 上記の例のように、あらかじめ name や age といった変数を用意し、それを data.frame() 関数に代入した場合は、それぞれの変数の名前がデータフレームの列名として使われます。
- 今回のように列数や要素数が少ない場合は、あらかじめ変数を用意せず、方法2のように data.frame() 関数の中で列の内容を直接記述するのも良いでしょう。
2.5.12 データフレームの列抽出
以下のようなデータフレーム df が定義されています。
このデータフレームから score 列のデータだけをベクトルとして取り出すコードを書いてください。
解答
df = data.frame(id = 1:3, score = c(80, 95, 70))
df$score
## [1] 80 95 70
df[, 2] # これでも可
## [1] 80 95 70
df[, "score"] # これでも可
## [1] 80 95 70
df[["score"]] # これでも可
## [1] 80 95 70
- データフレーム内の特定の列にアクセスするには データフレーム名$列名 という記法が最も一般的で便利です。
- 特殊なケースでは、$を使う以外の方法が必要になる場合があります。たとえば、列名を変数に入っている文字列を使って指定したい場合や、for 文で列を順番に処理する場合、あるいは列の位置(番号)しかわからない場合などです。
2.5.13 データフレームへの列の追加・更新
以下のデータフレーム df に、性別を表す gender という新しい列を追加してください。 gender 列の値はc("F", "M", "F")とします。
2.5.15 アンケートデータの集計
あなたは5人の顧客に対してアンケートを行い、年齢と満足度を調査しました。以下の手順に従ってデータを整理し、平均年齢を求めてください。
age(年齢データ)とsatisfaction(満足度データ)という2つの列を持つデータフレーム df を作成してください。
- age:
20, 35, NA, 42, 28という数値ベクトル - satisfaction:
"Low", "High", "Medium", "Low", "High"という文字列ベクトル
satisfaction 列を Low < Medium < High という順序を持つ因子型に変換してください。
回答者の平均年齢を計算してください。
2.5.16 テスト結果の行列操作とフィルタリング
あるクラスの3人の学生(A, B, C)が受けた4教科のテストの点数が手元にあります。以下の手順でデータの修正と確認を行ってください。
行列の作成: 以下の12個の数値を、3行4列の行列 scores にしてください。データは行方向(byrow = T)に埋めてください。
データ: 80, 95, 70, 60, 50, 45, 90, 30, 100, 85, 25, 80
赤点の修正: 40点未満(< 40)の点数は「追試」扱いとするため、行列内の該当する数値をすべて NA に書き換えてください。
データ抽出: 修正後の行列から、2人目の学生(2行目)の成績のみを取り出して表示してください。
解答
# 1. 行列の作成
data = c(80, 95, 70, 60, 50, 45, 90, 30, 100, 85, 25, 80)
scores = matrix(data, nrow = 3, ncol = 4, byrow = TRUE)
# 2. 条件に合う要素をNAに書き換え
scores[scores < 40] = NA
# 3. 2行目の抽出
scores[2, ]
## [1] 50 45 90 NA行列に対しても比較演算子(<など)を使うと、条件に合致する位置が TRUE になる論理行列が生成されます。これを利用して scores[scores < 40] = NA とすることで、条件に合う要素だけを一括で書き換えることができます。
2.5.17 複雑なデータ構造(リスト)の活用
ある実験データをまとめるために、異なる種類のデータを1つのリストに格納することにしました。
- 設定データの作成: config という名前の変数を作成します:
config = c(min = 0, max = 14) - 実験結果の作成: 数値ベクトル result_vec を作成してください。内容は
11:15です。 - リストの作成: これら2つを要素に持つリスト(変数名は experiment にする)を作成してください。リストの要素名は config と results にしてください。
- データの確認: 作成したリストを使い、「results の最大値」が、「config の max」以下であるかどうかを判定し、TRUE か FALSE を表示するコードを書いてください。
解答
# 1. 設定データの作成(名前付きベクトル)
config = c(min = 0, max = 14)
# 2. 実験結果の作成
result_vec = 11:15
# 3. リストの作成
experiment = list(config = config, results = result_vec)
# 4. データの取り出しと判定
# リストからベクトルを取り出し、さらにそのベクトルの最大値を計算
max_val = max(experiment$results)
# リストからconfigを取り出し、その中のmaxという名前の要素を取り出す
limit_val = experiment$config["max"]
# 比較
max_val <= limit_val
## max
## FALSE
# 変数を使わず、直接比較してもよい
max(experiment$results) <= experiment$config["max"]
## max
## FALSE