データの分析には、
といったプロセスがある。これらを Windows 上の R と RStudio で行う方法を概説しよう。
データはふつうEXCELのような表計算ソフトなどで行い、それを R のような統計解析ソフトに読み込むことが多い。分析の第一歩はデータを統計解析ソフトに読み込むことであるが、けっこう失敗しやすいので注意。
データを読み込む前に、作業ディレクトリ(作業フォルダともいう)を指定する。作業ディレクトリとは、Rがデフォルトでファイルの読み書きをするフォルダであり、特にパスを指定しなければ、R は作業フォルダのファイルを読みに行くし、ファイルを出力する場合もこのフォルダに出力のファイルを保存する。分析課題ごとに新しいフォルダを作ってそこに関連するファイルをまとめて保存しておくとよい。
作業フォルダを指定するには、RStudio のメニューの [Session] [Set Working Directory] [Choose Directory…] を選ぶとフォルダを選択するダイアログボックスが出てくるので、ここで選べばよい。
しかし、毎回これを行うのはけっこう面倒なので、 setwd() という関数をスクリプトの最初に書いてフォルダを指定したほうが簡単な場合も多い。 setwd() は
setwd(“作業ディレクトリのフルパス”)
という書式で指定する。例えば、以下のように。
setwd("C:/Users/Hiroshi/Dropbox/15_IJ_Courses/R_Practice")
スクリプトはすべて半角で書くこと。また R は大文字と小文字を区別しているので、SETWDと書いてもエラーになる。また Windows の場合ディレクトリの区切りは “\” ではなく “/” を使うので注意。
作業ディレクトリの指定を誤って、保存したファイルがどこに行ったのか、わからなくなる人がたまにいるが、そういう場合は、以下のように引数なしで getwd() を使えば作業ディレクトリの場所がわかる。
getwd()
## [1] "C:/Users/taroh/Dropbox/22G_Course/Rmd"
R には様々なサンプル・データがあらかじめ付属しており、これらを使って、分析の練習や様々な関数の挙動や性質を確認することができる。いくつかのパッケージのデータは最初からロードされており、データの名前をタイプするだけでいきなり使える。例えば、USArrests というサンプル・データをすべてそのまま表示するには、以下のようにすればよい。
USArrests
## Murder Assault UrbanPop Rape
## Alabama 13.2 236 58 21.2
## Alaska 10.0 263 48 44.5
## Arizona 8.1 294 80 31.0
## Arkansas 8.8 190 50 19.5
## California 9.0 276 91 40.6
## Colorado 7.9 204 78 38.7
## Connecticut 3.3 110 77 11.1
## Delaware 5.9 238 72 15.8
## Florida 15.4 335 80 31.9
## Georgia 17.4 211 60 25.8
## Hawaii 5.3 46 83 20.2
## Idaho 2.6 120 54 14.2
## Illinois 10.4 249 83 24.0
## Indiana 7.2 113 65 21.0
## Iowa 2.2 56 57 11.3
## Kansas 6.0 115 66 18.0
## Kentucky 9.7 109 52 16.3
## Louisiana 15.4 249 66 22.2
## Maine 2.1 83 51 7.8
## Maryland 11.3 300 67 27.8
## Massachusetts 4.4 149 85 16.3
## Michigan 12.1 255 74 35.1
## Minnesota 2.7 72 66 14.9
## Mississippi 16.1 259 44 17.1
## Missouri 9.0 178 70 28.2
## Montana 6.0 109 53 16.4
## Nebraska 4.3 102 62 16.5
## Nevada 12.2 252 81 46.0
## New Hampshire 2.1 57 56 9.5
## New Jersey 7.4 159 89 18.8
## New Mexico 11.4 285 70 32.1
## New York 11.1 254 86 26.1
## North Carolina 13.0 337 45 16.1
## North Dakota 0.8 45 44 7.3
## Ohio 7.3 120 75 21.4
## Oklahoma 6.6 151 68 20.0
## Oregon 4.9 159 67 29.3
## Pennsylvania 6.3 106 72 14.9
## Rhode Island 3.4 174 87 8.3
## South Carolina 14.4 279 48 22.5
## South Dakota 3.8 86 45 12.8
## Tennessee 13.2 188 59 26.9
## Texas 12.7 201 80 25.5
## Utah 3.2 120 80 22.9
## Vermont 2.2 48 32 11.2
## Virginia 8.5 156 63 20.7
## Washington 4.0 145 73 26.2
## West Virginia 5.7 81 39 9.3
## Wisconsin 2.6 53 66 10.8
## Wyoming 6.8 161 60 15.6
ただし、このようにデータをすべて表示させるのは、しばしば非常に鬱陶しいので、head()という関数を使うとよい。この関数は、
head(データフレーム名または行列名)
でデータの最初の数行だけを表示してくれるので、意外と便利である。例えば、以下のように。
head(USArrests)
## Murder Assault UrbanPop Rape
## Alabama 13.2 236 58 21.2
## Alaska 10.0 263 48 44.5
## Arizona 8.1 294 80 31.0
## Arkansas 8.8 190 50 19.5
## California 9.0 276 91 40.6
## Colorado 7.9 204 78 38.7
大半のパッケージのデータはいったんロード(呼び出し)しないと使えるようにならない。 例えば、AER というパッケージに含まれる CPS1985 というサンプル・データを使いたいとしよう。 いきなり以下のようにしてもうまくいかない。
library(AER)
CPS1985
## Error in eval(expr, envir, enclos): オブジェクト 'CPS1985' がありません
ちなみに library() はパッケージを呼び出すための関数で、
library(パッケージ名)
でパッケージを呼び出せる。パッケージは RStudio の Packages タブで使いたいパッケージにチェックをいれることでも呼び出せる。CPS1985 のようにあらかじめロードされていないサンプル・データをつかうためには、
data(データ名)
とすればよい。例えば以下のように。
data(CPS1985)
Rがエラー・メッセージを出さず、無反応ならばうまく行っているはずである。この後ならば以下のようにするなどして、CPS1985が使えるようになる。
head(CPS1985)
## wage education experience age ethnicity region gender occupation sector union married
## 1 5.10 8 21 35 hispanic other female worker manufacturing no yes
## 1100 4.95 9 42 57 cauc other female worker manufacturing no yes
## 2 6.67 12 1 19 cauc other male worker manufacturing no no
## 3 4.00 12 4 22 cauc other male worker other no no
## 4 7.50 12 17 35 cauc other male worker other no yes
## 5 13.07 13 9 28 cauc other male worker other yes no
R があらかじめもっているサンプル・データを確認するためには、
data()
とすればよい。サンプル・データのリストが表示される。ただし、ロードしていないパッケージのデータは表示されないので注意。
複数の変数からなるデータはふつうの行列でもよいが、行列は数値と文字の要素を混在させることができない。数値なら数値だけ、文字なら文字だけしか扱えない。データフレームという形式は、様々なタイプのデータをひとまとめにして扱えるので、便利である。R のサンプル・データのほとんどもデータフレームである。データフレームを作るには、data.frame() 関数を使うのが基本である。
data.frame(変数名 = ベクトル, 変数名 = ベクトル, …)
例えば以下のように。
dat1 <- data.frame(
sex = rep(c("Female", "Male"), 5), # スクリプトはコンマのあとなど途中で改行できる
age = rep(18:22, each = 2),
score = c(46, 7, 88, 54, 66, 44, 59, 35, 22, 70)
)
dat1
## sex age score
## 1 Female 18 46
## 2 Male 18 7
## 3 Female 19 88
## 4 Male 19 54
## 5 Female 20 66
## 6 Male 20 44
## 7 Female 21 59
## 8 Male 21 35
## 9 Female 22 22
## 10 Male 22 70
ベクトルの長さが変数によって異なると、エラーが出るので注意。
データフレームの中の特定の変数は、行列と同じように何列目の変数なのかを [, ] を使って取り出すこともできるし、
データフレーム名$変数名
としても同じように取り出せる。例えば以下のように。
dat1[, 3]
## [1] 46 7 88 54 66 44 59 35 22 70
dat1$score
## [1] 46 7 88 54 66 44 59 35 22 70
外部データの読み込みには、read.table() や read.csv() といった関数を使うが、これらが読み込めるデータの形式は、テキストファイルだけである。EXCELやSPSSなどのファイルを読み込める関数も gdata や foreign のようなパッケージにあるが、個人的には R でデータを読み込む場合は、CSV形式かタブ区切り形式のテキスト・ファイルにデータをいったん変換してから読み込むのが簡単だと感じている。一番最初の行に変数名を書いたCSV形式のデータ(1行目は変数名)を作業ディレクトリに保存した上で
read.csv(“ファイル名”)
とすればよい。例えば “sample.csv” というCSV形式のファイルを作業ディレクトリに保存し、
data1 <- read.csv("sample.csv")
とすれば、data1 という名前で R の中でそのデータを分析できるようになる。もちろんデータは作業ディレクトリ以外の場所においておいて、以下のようにフルパスを指定して読み込んでもよい。
data1 <- read.csv("c:/myfolder/temp/sample.csv")
また、以下の関数を引数無しでファイル名の代わりに書いておくと、ダイアログボックスが開いて、読み込むファイルを選ぶことができる。
choose.files()
data1 <- read.csv(choose.files()) # ファイルを選ぶダイアログボックスが開く
サンプル・データの場合、ヘルプを呼び出すとサンプル・データについてある程度は解説してあるので、参考にするとよい。例えば、以下のように。
?CPS1985
ちなみに “?” は
?関数名
で関数のヘルプを呼び出すことができる。例えば、以下のように。
?head
データの中身を見るには、すでに述べたようにデータの名前をタイプするという方法がもっとも単純だが、データのサイズが大きいと表示しきれず、かえって不便である。これもすでに述べたように head() でも見られるが、変数の数が多いとやはり見にくい。R の場合、変数の数があまり多いデータを読み込むと使いにくいので、必要な変数だけを含んだデータを読み込んだほうがいいように思われる。
簡単な記述統計は、
summary(データフレーム名)
で表示できる。例えば、以下のように。
summary(CPS1985)
## wage education experience age ethnicity region
## Min. : 1.000 Min. : 2.00 Min. : 0.00 Min. :18.00 cauc :440 south:156
## 1st Qu.: 5.250 1st Qu.:12.00 1st Qu.: 8.00 1st Qu.:28.00 hispanic: 27 other:378
## Median : 7.780 Median :12.00 Median :15.00 Median :35.00 other : 67
## Mean : 9.024 Mean :13.02 Mean :17.82 Mean :36.83
## 3rd Qu.:11.250 3rd Qu.:15.00 3rd Qu.:26.00 3rd Qu.:44.00
## Max. :44.500 Max. :18.00 Max. :55.00 Max. :64.00
## gender occupation sector union married
## male :289 worker :156 manufacturing: 99 no :438 no :184
## female:245 technical :105 construction : 24 yes: 96 yes:350
## services : 83 other :411
## office : 97
## sales : 38
## management: 55
数値型の変数と文字型の変数(あるいは因子、論理型の変数)では要約の仕方が異なり、文字型の場合は、各カテゴリの度数を示す度数分布表が示され、数値型の変数の場合は平均値などの統計が示される。各項目の意味は、下記の通り。
項目 | 意味 |
---|---|
Min. | 最小値 |
1st Qu. | 第1四分位点 |
Median | 中央値 |
Mean | 平均値 |
3rd Qu. | 第3四分位点 |
Max. | 最大値 |
NA’s | 欠損値の数 |
この他にも標準偏差や分散が知りたい場合は、
sd(データ名$変数名)
var(データ名$変数名)
で計算できる。例えば以下のように。
sd(CPS1985$wage)
## [1] 5.139097
var(CPS1985$wage)
## [1] 26.41032
もちろん sd や var の引数は、データフレーム中の変数だけでなく数値ベクトルであれば何でもよい。
x <- c(5, 4, 6, 7, 20)
sd(x)
## [1] 6.580274
データが得られない場合などは欠損値を用いることが多い。欠損値には、NA を用いる。例えば、5人分の身長と体重のデータを取ったが、2人目の身長と 5人目の人の体重がわからなかった場合、以下のように入力する。
身長 <- c(160, NA, 180, 155, 172)
体重 <- c(50, 55, 70, NA, 70)
デフォルトでは欠損値があるとエラーが出て計算されない関数も多い。sd( ), var( ), mean( ), sum( ) といった関数の場合、欠損値を除外して計算する場合は、“, na.rm = TRUE” というオプションを付ける。
x <- c(1, 4, 6, 5, NA)
sd(x)
## [1] NA
sd(x, na.rm = T)
## [1] 2.160247
複数の変数について一つ一つ標準偏差を計算するのは面倒なので、一度に計算してしまいたい場合もある。そのような場合はいくつかやり方があるが、ここでは apply() という関数を使ったやり方を紹介しよう。
apply(標準偏差を計算したいデータフレーム名, 2, sd)
で計算できる。例えば以下のように。
d <- CPS1985[,1:4] # [, 1:4]はデータフレームや行列の1:4行目だけを取り出す指定
head(d)
## wage education experience age
## 1 5.10 8 21 35
## 1100 4.95 9 42 57
## 2 6.67 12 1 19
## 3 4.00 12 4 22
## 4 7.50 12 17 35
## 5 13.07 13 9 28
apply(d, 2, sd)
## wage education experience age
## 5.139097 2.615373 12.379710 11.726573
やはり、欠損値がある場合は、以下のように “,na.rm = T”とオプションを付ければよい。
apply(d, 2, sd, na.rm = T)
var() の場合はそのままデータフレームや行列を引数とすれば、分散・共分散行列を返すので、対角線の値がそれぞれの変数の分散である。
(var.cps <- var(d) ) # () でくくると代入するだけでなく中身も見られる。
## wage education experience age
## wage 26.410316 5.133282 5.538773 10.664731
## education 5.133282 6.840174 -11.418801 -4.601001
## experience 5.538773 -11.418801 153.257222 141.972170
## age 10.664731 -4.601001 141.972170 137.512508
diag(var.cps) # diag(行列名)で正方行列の主対角線の要素を取り出してくれる。
## wage education experience age
## 26.410316 6.840174 153.257222 137.512508
度数分布表はグラフで見るのが基本であるが、数や比率をきちんと出したい場合もある。そのような場合、xtabs() 関数を使う。書式は以下の通り。
xtabs(~ 変数名, data = データフレーム名)
以下は使用例。
xtabs(~ ethnicity, data = CPS1985)
## ethnicity
## cauc hispanic other
## 440 27 67
xtabs() でできることはほとんど table() でもできるが、スクリプトの書き方が異なる。
table(ベクトル)
以下が使用例
table(CPS1985 $ ethnicity)
##
## cauc hispanic other
## 440 27 67
相対度数(個々のカテゴリの比率)は prop.table() で計算できる。
prop.table(度数分布表)
以下が使用例。
tab.ethnicity <- xtabs(~ ethnicity, data = CPS1985)
prop.table(tab.ethnicity)
## ethnicity
## cauc hispanic other
## 0.8239700 0.0505618 0.1254682
2つ以上のカテゴリカルな変数を組み合わせてサンプルを分割する表をクロス表とか分割表と呼ぶ。クロス表も xtabs() や table() で作れる。
xtabs(~ 変数1 + 変数2, data = データフレーム名)
以下が使用例。
xtabs(~ gender + ethnicity, data = CPS1985)
## ethnicity
## gender cauc hispanic other
## male 236 14 39
## female 204 13 28
上の表は male かつ cauc の人は 236人、female かつ other の人は 28 人、といった意味になる。同じことは table() でもできる。これらの 236、 28 といった数はセル度数と呼ばれたりする。
table(変数1, 変数2)
table(CPS1985$gender, CPS1985$ethnicity)
##
## cauc hispanic other
## male 236 14 39
## female 204 13 28
クロス表の各セル度数の比率を計算する場合も prop.table() を使うが、分母を何にするかによって、3通り(3つ以上の変数を使ったクロス表(後述)ならもっとたくさん)の計算の仕方がある。
prop.table(クロス表)
とすればよい。以下使用例。
tab1 <- xtabs(~ gender + ethnicity, data = CPS1985)
prop.table(tab1)
## ethnicity
## gender cauc hispanic other
## male 0.44194757 0.02621723 0.07303371
## female 0.38202247 0.02434457 0.05243446
1行1列目の値は、 tab1 の1行1列目のセル度数 236 を総度数 534 で割った値である。ほかのセルも、すべて tab1 のセル度数を 534 で割った値になる。これに決まった名前はないが、総パーセントと呼んでおく。
rowSums(tab1)
## male female
## 289 245
tab1 [1, ] / rowSums(tab1) [1] # 1行目の 3つのセル度数は、1行目のセル度数の総和で割る
## cauc hispanic other
## 0.81660900 0.04844291 0.13494810
tab1 [2, ] / rowSums(tab1) [2] # 2行目の 3つのセル度数は、2行目の総和で割る
## cauc hispanic other
## 0.83265306 0.05306122 0.11428571
1つ目のベクトルは、男性の総数に占める白人男性(male かつ cauc)の比率、ヒスパニック男性(male かつ hispanic) の比率、その他の男性の比率 (male かつ other) の比率をあらわし、2つ目のベクトルも男性と同じように女性の総数に占める各エスニシティの比率を示す。これを 行パーセント と呼んでおく。また、男性の総数やヒスパニックの総数のように、行または列の総和を 周辺度数 (marginal frequency) と呼ぶ。これらを周辺度数と呼ぶのは、以下のようにクロス表の周辺に記載するのが一般的だからかもしれない。
addmargins(tab1) # addmargins(クロス表) で周辺度数を書き加えたクロス表を返す
## ethnicity
## gender cauc hispanic other Sum
## male 236 14 39 289
## female 204 13 28 245
## Sum 440 27 67 534
行パーセントは prop.table() でも計算できる。
prop.table(クロス表, margin = 1) # margin = は省略可
以下は使用例。
prop.table(tab1, margin = 1)
## ethnicity
## gender cauc hispanic other
## male 0.81660900 0.04844291 0.13494810
## female 0.83265306 0.05306122 0.11428571
prop.table(tab1, 1)
## ethnicity
## gender cauc hispanic other
## male 0.81660900 0.04844291 0.13494810
## female 0.83265306 0.05306122 0.11428571
colSums(tab1)
## cauc hispanic other
## 440 27 67
tab1 [, 1] / colSums(tab1) [1]
## male female
## 0.5363636 0.4636364
tab1 [, 2] / colSums(tab1) [2]
## male female
## 0.5185185 0.4814815
tab1 [, 3] / colSums(tab1) [3]
## male female
## 0.5820896 0.4179104
これらは、各エスニシティ内部での男女の比率を示す。列パーセントも以下のようにして prop.table() で計算できる。
prop.table(クロス表, margin = 2) # margin = は省略可
以下は使用例。
prop.table(tab1, margin = 2)
## ethnicity
## gender cauc hispanic other
## male 0.5363636 0.5185185 0.5820896
## female 0.4636364 0.4814815 0.4179104
以下のように 3つ以上の変数を組み合わせてクロス表を作ることもできる。
xtabs(~ 変数1 + 変数2 + 変数3, data = データフレーム名)
以下使用例。
xtabs(~ gender + union + ethnicity, data = CPS1985)
## , , ethnicity = cauc
##
## union
## gender no yes
## male 186 50
## female 181 23
##
## , , ethnicity = hispanic
##
## union
## gender no yes
## male 10 4
## female 12 1
##
## , , ethnicity = other
##
## union
## gender no yes
## male 25 14
## female 24 4
上の表では白人かつ男性かつ組合に加入していない人が 186人、ヒスパニックかつ女性かつ組合に加入している人が 1人、という具合に読めばよい。さらに4つ目の変数を組み合わせたければ、
xtabs(~ 変数1 + 変数2 + 変数3 + 変数4, data = データフレーム名)
という具合にすればよいが、煩雑なのであまり使うことはないだろう。3変数を組み合わせたクロス表を三重クロス表、四変数を組み合わせたクロス表を四重クロス表というが、二重クロス表という言い方は聞いたことがない。
やはり prop.table() を使えば計算できるが、7通りの計算の仕方があり、ぜんぶ示すのは煩雑である。7通りあると言っても、三種類に分類できるので、計算例を示す。
tab2 <- xtabs(~ gender + union + ethnicity, data = CPS1985)
# 総パーセント:各セル度数をそれらの総和で割る
prop.table(tab2)
## , , ethnicity = cauc
##
## union
## gender no yes
## male 0.348314607 0.093632959
## female 0.338951311 0.043071161
##
## , , ethnicity = hispanic
##
## union
## gender no yes
## male 0.018726592 0.007490637
## female 0.022471910 0.001872659
##
## , , ethnicity = other
##
## union
## gender no yes
## male 0.046816479 0.026217228
## female 0.044943820 0.007490637
# 一行目のセル度数は、男性の人数の総和で割り、二行目のセル度数は女性の人数の総和で割る
round( # 数字が多すぎるので、四捨五入
prop.table(tab2, 1),
2
)
## , , ethnicity = cauc
##
## union
## gender no yes
## male 0.64 0.17
## female 0.74 0.09
##
## , , ethnicity = hispanic
##
## union
## gender no yes
## male 0.03 0.01
## female 0.05 0.00
##
## , , ethnicity = other
##
## union
## gender no yes
## male 0.09 0.05
## female 0.10 0.02
一行目(male) は、男性のセル度数を男性の総数でわったもので、それらをすべて足し合わせると \(0.64 + 0.17 + 0.03 + 0.01 + 0.09 + 0.05 \fallingdotseq 1\) になる。
# 性別とエスニシティを組み合わせた周辺度数で、対応するセル度数を割る。
round(
prop.table(tab2, margin = c(1, 3)),
2
)
## , , ethnicity = cauc
##
## union
## gender no yes
## male 0.79 0.21
## female 0.89 0.11
##
## , , ethnicity = hispanic
##
## union
## gender no yes
## male 0.71 0.29
## female 0.92 0.08
##
## , , ethnicity = other
##
## union
## gender no yes
## male 0.64 0.36
## female 0.86 0.14
変数の分布を探索的にチェックする場合、グラフの作成が非常に有益である。
連続変数の場合はヒストグラムをまずは作るのが基本であろう。ヒストグラムは hist() 関数で作る。
hist(データフレーム名$変数名)
例えば以下のように。
hist(CPS1985$wage)
離散変数(文字型のデータ)の場合は度数分布表を単純にグラフにすればよい。そのためには、plot()関数で
plot(データフレーム名$変数名)
とすればよい。例えば以下のように。
plot(CPS1985$ ethnicity)
連続変数どうしの関係は散布図で見る。これにも plot() を使う。
plot(y軸に配する変数名 ~ x軸に配する変数名, data = データフレーム名)
例えば、以下のようにする。
plot(wage ~ experience, data = CPS1985)
すべての変数の組み合わせの散布図を作るのは、いちいちスクリプトを書いていてはたいへんなので、以下のようにする。
plot(データフレーム名)
例えば、以下のようにする。
plot(CPS1985[, 1:4])
上の図で1行2列目のグラフは縦軸が wage、 横軸が education の散布図である。一番右上のグラフは縦軸が wage で横軸が age である。一般にあるグラフと同じ列(上か下)にある文字がそのグラフの横軸の変数を示し、同じ行(右か左)にある文字がそのグラフの縦軸の変数を示す。
教育年数のようにいちおう数値型であっても実際には細かい数値をとりえない場合、散布図の点が完全に重なってしまい、どこに点が集中しているのかわからない。そのような場合、jitter() という関数を使うとほんの少し点をずらして散布図を見やすくすることができる。
jitter(ベクトル)
こうすると、元のベクトルに平均が 0 でちいさな分散の一様分布の乱数を足しあわせたベクトルを返してくれる。具体的には、以下のように使うとよい。
plot(wage ~ jitter(education), data = CPS1985)
こうするとどのあたりの事例が多いのかよくわかる。
グループ別に数値型の変数の分布を見たい場合は、箱ひげ図を使うのが基本である。箱ひげ図は、
plot(数値型の変数名 ~ グループ分けするためのカテゴリカル変数名, data = データフレーム名)
または
boxplot(数値型の変数名 ~ グループ分けするためのカテゴリカル変数名, data = データフレーム名)
とすれば作れる。
plot(wage ~ ethnicity, data = CPS1985)
離散変数どうしの関係は、モザイクプロットを上手に作れれば見やすい。これも散布図や箱ひげ図と同じように plot() で作れる。例えば以下のように。
plot(union ~ gender, data = CPS1985)
この例では、棒の幅が男女の比率に比例するように作られている。そして濃いグレーの部分の高さが男女それぞれの組合未加入率を示している。
spineplot() でも同じものが作れる。
変数の操作はベクトルを使った計算なので、ベクトルを使った計算の応用出来さえすれば、新しい知識はあまり必要ない。
CPS1985 の wage という変数は時給なので、これから1日8時間働いた場合の日給を計算したいなら、以下のようにすればよい。
CPS1985$wage.d <- CPS1985$wage * 8
head(CPS1985)
## wage education experience age ethnicity region gender occupation sector union married
## 1 5.10 8 21 35 hispanic other female worker manufacturing no yes
## 1100 4.95 9 42 57 cauc other female worker manufacturing no yes
## 2 6.67 12 1 19 cauc other male worker manufacturing no no
## 3 4.00 12 4 22 cauc other male worker other no no
## 4 7.50 12 17 35 cauc other male worker other no yes
## 5 13.07 13 9 28 cauc other male worker other yes no
## wage.d
## 1 40.80
## 1100 39.60
## 2 53.36
## 3 32.00
## 4 60.00
## 5 104.56
CPS1985の最後の列に、新しく wage.d という変数が付け加えられる。新しい変数を作ったときは、必ず意図したとおりに新しい変数が作られているかチェックすること。エラーが出ないからといって失敗していないという保証はない。
また、自然対数などの関数も使える。時給を対数変換した変数を新しく作りたいならば、以下のようにすれば良い。
CPS1985$wage.log <- log(CPS1985$wage)
head(CPS1985)
## wage education experience age ethnicity region gender occupation sector union married
## 1 5.10 8 21 35 hispanic other female worker manufacturing no yes
## 1100 4.95 9 42 57 cauc other female worker manufacturing no yes
## 2 6.67 12 1 19 cauc other male worker manufacturing no no
## 3 4.00 12 4 22 cauc other male worker other no no
## 4 7.50 12 17 35 cauc other male worker other no yes
## 5 13.07 13 9 28 cauc other male worker other yes no
## wage.d wage.log
## 1 40.80 1.629241
## 1100 39.60 1.599388
## 2 53.36 1.897620
## 3 32.00 1.386294
## 4 60.00 2.014903
## 5 104.56 2.570320
変数をZ得点(平均 0 標準偏差 1 の変数)に変換したいならば、scale() 関数を使えばよい。
scale(ベクトル)
例えば年齢をz以下のように。
CPS1985$age.z <- scale(CPS1985$age)
mean(CPS1985$age.z)
## [1] -2.084775e-16
sd(CPS1985$age.z)
## [1] 1
変数のいくつかのカテゴリや数値をまとめて新しい値やカテゴリを作りたい場合がある。やり方はいくつかあるが、SPSS の recode ライクな関数から紹介しよう。 SPSSの recode に近い働きをする関数をいくつかのパッケージが用意しているが、ここでは memisc パッケージの recode() 関数を紹介しよう(同じ名前の関数を複数のパッケージがもっている場合、最後に読み込んだパッケージの関数が用いられるので注意。recode() は car というパッケージにも含まれている)。これは以下のような書式で使う。
recode(ベクトル, 新しい値 <- 古い値(のベクトル), 新しい値 <- 古い値(のベクトル), … )
例えば、CPS1985 の occupation という変数は5つのカテゴリからなるが、これを upper, middle, lower の 3カテゴリにまとめなおしたいとしよう。その場合、以下のようにすればよい。
library(memisc)
## 要求されたパッケージ lattice をロード中です
## 要求されたパッケージ MASS をロード中です
##
## 次のパッケージを付け加えます: 'memisc'
## 以下のオブジェクトは 'package:car' からマスクされています:
##
## recode
## 以下のオブジェクトは 'package:stats' からマスクされています:
##
## contr.sum, contr.treatment, contrasts
## 以下のオブジェクトは 'package:base' からマスクされています:
##
## as.array
CPS1985$occ3 <- recode(CPS1985$occupation,
"upper" <- c("technical", "management"),
"middle" <- c("services", "office", "sales"),
"lower" <- "worker"
)
xtabs(~occupation + occ3, CPS1985) # もとの変数と新しい変数のクロス表
## occ3
## occupation upper middle lower
## worker 0 0 156
## technical 105 0 0
## services 0 83 0
## office 0 97 0
## sales 0 38 0
## management 55 0 0
xtabs() はクロス表を作る関数で、以下のような書式で書く。
xtabs(~ 行の変数名 + 列の変数名, データ名)
連続変数をいくつかのカテゴリにまとめ直す場合、cut() という関数が便利である。書式は以下の通り。
cut(データ名$変数名, 区切り位置を示すベクトル)
ただし区切り位置は上限値と下限値も含まなければならない。
例えば、労働経験年数が 0~9年、10~19年、20~29年、30年以上という4つのカテゴリからなる変数を作りたい場合、以下のようにすればよい。
CPS1985$exp4 <- cut(CPS1985$experience, c(-1, 9, 19, 29, 60))
xtabs(~ exp4, CPS1985)
## exp4
## (-1,9] (9,19] (19,29] (29,60]
## 156 183 91 104
xtabs(~ experience + exp4, CPS1985) [1 : 25, ] # 長すぎるので最初の25行だけ表示
## exp4
## experience (-1,9] (9,19] (19,29] (29,60]
## 0 11 0 0 0
## 1 12 0 0 0
## 2 15 0 0 0
## 3 18 0 0 0
## 4 16 0 0 0
## 5 15 0 0 0
## 6 17 0 0 0
## 7 18 0 0 0
## 8 19 0 0 0
## 9 15 0 0 0
## 10 0 23 0 0
## 11 0 11 0 0
## 12 0 18 0 0
## 13 0 23 0 0
## 14 0 28 0 0
## 15 0 18 0 0
## 16 0 22 0 0
## 17 0 15 0 0
## 18 0 11 0 0
## 19 0 14 0 0
## 20 0 0 13 0
## 21 0 0 7 0
## 22 0 0 10 0
## 23 0 0 6 0
## 24 0 0 11 0
この例の場合、experienceを \(x\) と表記すると、新しく作った exp4 という変数の4つのカテゴリは \(-1<x \leq 9\), \(9 < x \leq 19\), \(19 < x \leq 29\), \(29 < x \leq 60\) に対応している。注意すべきなのは、中間の区切り値 9, 19, 29 は値の小さい方のカテゴリに含まれるという点と、-1 と 60 のように上限と下限の値も区切り値として指定する必要があるということである。cut() で作ったカテゴリの名前を指定したい場合は、, labels = カテゴリの名前のベクトル という引数をつける。例えば以下のように。
CPS1985$exp4 <- cut(CPS1985$experience, c(-1, 9, 19, 29, 60),
labels = c("0~9年", "10~19年", "20~29年", "30年以上")
)
xtabs(~ exp4, CPS1985)
## exp4
## 0~9年 10~19年 20~29年 30年以上
## 156 183 91 104
上の労働経験年数を 4カテゴリに分類する例は、
データフレーム名$ 新しい変数名 [条件式] <- 新しい値
という書式でもできる。具体的には以下のようにすればよい。
x <- CPS1985$experience # 何回も参照するので短い名前をつけておく
CPS1985$ exp4 [x <= 9] <- "0~9年"
CPS1985$ exp4 [x >= 10 & x <= 19] <- "10~19年"
CPS1985$ exp4 [x >= 20 & x <= 29] <- "20~29年"
CPS1985$ exp4 [x >= 30] <- "30年以上"
xtabs( ~ exp4, CPS1985)
## exp4
## 0~9年 10~19年 20~29年 30年以上
## 156 183 91 104
この方法は煩雑に思える場合もあるが、柔軟で汎用性が高いのでぜひ習得してほしい。なおこのままではただの文字列で因子になっていないので、以下のように因子に変換しておいた方がいい。
CPS1985$exp4 <- factor(CPS1985$ exp4)
論理演算子を使うと比較的簡単に二値変数が作れる。例えば教育年数が 13年以上のとき 1、13年未満のとき 0 をとるような二値変数を作りたい場合、以下のようにすればよい。
CPS1985$ edu13 <- CPS1985$ education >= 13
xtabs(~ edu13, CPS1985)
## edu13
## FALSE TRUE
## 302 232
xtabs(~ education + edu13, CPS1985)
## edu13
## education FALSE TRUE
## 2 1 0
## 3 1 0
## 4 1 0
## 5 1 0
## 6 3 0
## 7 5 0
## 8 15 0
## 9 12 0
## 10 17 0
## 11 27 0
## 12 219 0
## 13 0 37
## 14 0 56
## 15 0 13
## 16 0 71
## 17 0 24
## 18 0 31
1, 0 ではなく TRUE と FALSE という2つの値をとるが、数値計算をすると TRUE と FALSE はそれぞれ 1 と 0 に置き換えて計算されるので、1, 0 の二値変数と同じである。
sum(CPS1985$edu13) # 1, 0 に変換されるので、TRUEの数と同じ値が返される
## [1] 232
特定の条件を満たすケースだけを取り出したデータを作りたい場合がある。その場合、データフレームでも行列と同じように処理できる。
データフレーム名 [条件式, ]
例えば CPS1985 から女性のケースだけを取り出したデータを作りたい場合、以下のようにすればよい。
dat2 <- CPS1985 [CPS1985$ gender == "female", ]
head(dat2)
## wage education experience age ethnicity region gender occupation sector union married wage.d
## 1 5.10 8 21 35 hispanic other female worker manufacturing no yes 40.80
## 1100 4.95 9 42 57 cauc other female worker manufacturing no yes 39.60
## 20 5.71 12 16 34 cauc other female worker manufacturing yes yes 45.68
## 28 3.35 12 8 26 cauc other female worker manufacturing no yes 26.80
## 31 4.00 12 46 64 cauc south female worker other no no 32.00
## 33 5.00 17 1 24 cauc south female worker other no no 40.00
## wage.log age.z occ3 exp4 edu13
## 1 1.629241 -0.1563401 lower 20~29年 FALSE
## 1100 1.599388 1.7197409 lower 30年以上 FALSE
## 20 1.742219 -0.2416165 lower 10~19年 FALSE
## 28 1.208960 -0.9238278 lower 0~9年 FALSE
## 31 1.386294 2.3166758 lower 30年以上 FALSE
## 33 1.609438 -1.0943806 lower 0~9年 TRUE
summary(dat2$ gender)
## male female
## 0 245
また、年齢が30歳未満のケースだけを取り出したデータを作りたい場合、以下のようにすればよい。
dat3 <- CPS1985 [CPS1985$ age < 30, ]
head(dat3)
## wage education experience age ethnicity region gender occupation sector union married wage.d
## 2 6.67 12 1 19 cauc other male worker manufacturing no no 53.36
## 3 4.00 12 4 22 cauc other male worker other no no 32.00
## 5 13.07 13 9 28 cauc other male worker other yes no 104.56
## 7 19.47 12 9 27 cauc other male worker other no no 155.76
## 9 8.75 12 9 27 cauc other male worker other no no 70.00
## 22 3.75 12 9 27 cauc other male worker other no no 30.00
## wage.log age.z occ3 exp4 edu13
## 2 1.897620 -1.5207626 lower 0~9年 FALSE
## 3 1.386294 -1.2649334 lower 0~9年 FALSE
## 5 2.570320 -0.7532749 lower 0~9年 TRUE
## 7 2.968875 -0.8385513 lower 0~9年 FALSE
## 9 2.169054 -0.8385513 lower 0~9年 FALSE
## 22 1.321756 -0.8385513 lower 0~9年 FALSE
summary(dat3$ age)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 18.00 22.00 25.00 24.45 27.00 29.00
R の場合、分析に使う変数だけからなるデータフレームを作ったほうが、しばしば分析は簡単になるので、必要な変数だけを取り出して新しいデータフレームを作ることがおすすめである。そのような場合、
データフレーム名[, 取り出す変数が何列目かを示すベクトル]
または、
データフレーム名[, 取り出す変数名のベクトル]
とすればよい。後者のほうがオススメ。なぜなら、データの操作を試行錯誤している段階では、変数の順番が入れ替わったり、途中に新しい変数が挿入されたりすることもあるから。そうすると、取り出す変数の列番号がずれるが、それを忘れて取り出す変数の列番号を修正しないと、思わぬ失敗につながる。私は何度かやらかした。
スクリプトの例。CPS1985 の 1, 4, 7 列目の wage, age, gender の 3 つの変数だけからなるデータフレームを作る場合、以下のようにすればよい。
dat4 <- CPS1985 [, c(1, 4, 7)]
head(dat4)
## wage age gender
## 1 5.10 35 female
## 1100 4.95 57 female
## 2 6.67 19 male
## 3 4.00 22 male
## 4 7.50 35 male
## 5 13.07 28 male
dat4 <- CPS1985 [, c("wage", "age", "gender")]
head(dat4)
## wage age gender
## 1 5.10 35 female
## 1100 4.95 57 female
## 2 6.67 19 male
## 3 4.00 22 male
## 4 7.50 35 male
## 5 13.07 28 male
変数名をいちいち ” ” でくくったり、使いたい変数が何列目か確認するのが意外と面倒なので、subset( ) という関数が一部のケースと変数を取り出したいとき意外と重宝する。
subset(データフレーム名, ケースを選択する条件, 取り出す変数名のベクトル)
例えば CPS1985 から30歳未満の男性のケースだけを取り出し、wage, experience, education の3変数だけを用いたい場合は、以下のようにすればよい。
dat5 <- subset(CPS1985, gender == "male" & age < 30, c(wage, experience, education))
head(dat5)
## wage experience education
## 2 6.67 1 12
## 3 4.00 4 12
## 5 13.07 9 13
## 7 19.47 9 12
## 9 8.75 9 12
## 22 3.75 9 12
欠損値のあるケースの扱いは、実際のデータ分析では重要である。伝統的にはリストワイズ法(欠損値のあるケースは分析から除外)がよく用いられてきたが、リストワイズ法を用いる場合、あらかじめ欠損値を除外したデータフレームを作っておいたほうが便利な場合がしばしばある。その場合、na.omit() 関数を使う。以下のような書式でリストワイズで欠損値を含むケースを除外したデータフレームを返してくれる。
na.omit(欠損値を含んだデータフレーム)
例えば以下のようにする。
# 欠損値を含んだ架空のデータを作る
dat6 <- data.frame(sex = gl(2, 5, labels = c("female", "male")),
score = 1:10)
dat6$ sex [2] <- NA
dat6$ score [6:7] <- NA
dat6
## sex score
## 1 female 1
## 2 <NA> 2
## 3 female 3
## 4 female 4
## 5 female 5
## 6 male NA
## 7 male NA
## 8 male 8
## 9 male 9
## 10 male 10
# リストワイズで欠損値を含むケースを除外
dat7 <- na.omit(dat6)
dat7
## sex score
## 1 female 1
## 3 female 3
## 4 female 4
## 5 female 5
## 8 male 8
## 9 male 9
## 10 male 10
回帰分析は、もっとも重要かつ基本的な分析法の一つであるが、lm( ) 関数で計算できる。
lm(従属変数名 ~ 独立変数名, data = データフレーム名)
例えば以下のように。
lm(wage ~ age, data = CPS1985)
##
## Call:
## lm(formula = wage ~ age, data = CPS1985)
##
## Coefficients:
## (Intercept) age
## 6.16747 0.07755
しかし、これでは係数が有意か、決定係数はどの程度かなど詳しいことがわからないので、さらに summary( ) で詳しい結果を引き出す。
summary(回帰分析の結果)
例えば以下のように。
lm1 <- lm(wage ~ age, data = CPS1985)
summary(lm1)
##
## Call:
## lm(formula = wage ~ age, data = CPS1985)
##
## Residuals:
## Min 1Q Median 3Q Max
## -8.425 -3.503 -1.106 2.276 36.704
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 6.16747 0.72280 8.533 < 2e-16 ***
## age 0.07755 0.01870 4.147 3.92e-05 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 5.063 on 532 degrees of freedom
## Multiple R-squared: 0.03132, Adjusted R-squared: 0.0295
## F-statistic: 17.2 on 1 and 532 DF, p-value: 3.917e-05
散布図に回帰直線を引きたい場合は、まず散布図を作り、単回帰分析をし、その結果から abline( ) 関数で、
abline(回帰分析の結果)
とする。例えば以下のように。
plot(wage ~ age, data = CPS1985)
abline(lm1)
重回帰分析の場合は、複数の独立変数を “+” でつないで指定する。例えば以下のように。
lm2 <- lm(wage ~ age + education + experience, data = CPS1985)
summary(lm2)
##
## Call:
## lm(formula = wage ~ age + education + experience, data = CPS1985)
##
## Residuals:
## Min 1Q Median 3Q Max
## -8.351 -2.857 -0.599 1.994 36.336
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -4.76987 7.04271 -0.677 0.499
## age -0.02241 1.15475 -0.019 0.985
## education 0.94833 1.15524 0.821 0.412
## experience 0.12756 1.15571 0.110 0.912
##
## Residual standard error: 4.604 on 530 degrees of freedom
## Multiple R-squared: 0.202, Adjusted R-squared: 0.1975
## F-statistic: 44.73 on 3 and 530 DF, p-value: < 2.2e-16
カテゴリカル変数もそのまま独立変数として指定すれば、自動的に最初のカテゴリを基準とするダミー変数としてモデルに投入される。例えば以下のように。
lm3 <- lm(wage ~ age + education + ethnicity, data = CPS1985)
summary(lm3)
##
## Call:
## lm(formula = wage ~ age + education + ethnicity, data = CPS1985)
##
## Residuals:
## Min 1Q Median 3Q Max
## -8.302 -2.900 -0.655 2.087 36.212
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -5.26002 1.30800 -4.021 6.63e-05 ***
## age 0.10479 0.01722 6.085 2.24e-09 ***
## education 0.81050 0.07799 10.393 < 2e-16 ***
## ethnicityhispanic -0.40965 0.92267 -0.444 0.657
## ethnicityother -0.85043 0.60450 -1.407 0.160
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 4.599 on 529 degrees of freedom
## Multiple R-squared: 0.2051, Adjusted R-squared: 0.1991
## F-statistic: 34.13 on 4 and 529 DF, p-value: < 2.2e-16
x という変数の二乗項をモデルに加えたい場合、
I(x ^ 2)
という項を独立変数として指定すればよい。例えば以下のように。
lm4 <- lm(wage ~ age + I(age ^ 2), data = CPS1985)
summary(lm4)
##
## Call:
## lm(formula = wage ~ age + I(age^2), data = CPS1985)
##
## Residuals:
## Min 1Q Median 3Q Max
## -9.396 -3.273 -1.016 1.935 38.157
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -3.672133 2.274396 -1.615 0.107
## age 0.618912 0.120294 5.145 3.77e-07 ***
## I(age^2) -0.006761 0.001485 -4.554 6.54e-06 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 4.971 on 531 degrees of freedom
## Multiple R-squared: 0.06772, Adjusted R-squared: 0.06421
## F-statistic: 19.29 on 2 and 531 DF, p-value: 8.207e-09
一般にモデルの式の中で “+, -, /, *” といった二項演算子を使う場合は I() でくくってやる必要がある。例えば、age をそのまま独立変数とするのではなく、平均値でセンタリング(この変数の値からこの変数の平均値を引くこと)して使う場合、以下のようにする。
lm4.1 <- lm(wage ~ I(age - mean(age)), data = CPS1985)
summary(lm4.1)
##
## Call:
## lm(formula = wage ~ I(age - mean(age)), data = CPS1985)
##
## Residuals:
## Min 1Q Median 3Q Max
## -8.425 -3.503 -1.106 2.276 36.704
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 9.02406 0.21909 41.190 < 2e-16 ***
## I(age - mean(age)) 0.07755 0.01870 4.147 3.92e-05 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 5.063 on 532 degrees of freedom
## Multiple R-squared: 0.03132, Adjusted R-squared: 0.0295
## F-statistic: 17.2 on 1 and 532 DF, p-value: 3.917e-05
変数を自然対数に変換して使う場合は、I() は必要なく、 log() をモデルの式の中で指定してやればよい。例えば以下のように。
lm4.2 <- lm(log(wage) ~ occupation + sector, data = CPS1985)
summary(lm4.2)
##
## Call:
## lm(formula = log(wage) ~ occupation + sector, data = CPS1985)
##
## Residuals:
## Min 1Q Median 3Q Max
## -2.35040 -0.34500 -0.01735 0.33188 1.46785
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 2.06602 0.05102 40.491 < 2e-16 ***
## occupationtechnical 0.42008 0.06547 6.417 3.11e-10 ***
## occupationservices -0.18889 0.07222 -2.615 0.00917 **
## occupationoffice -0.01626 0.06768 -0.240 0.81028
## occupationsales -0.06339 0.09077 -0.698 0.48524
## occupationmanagement 0.41048 0.07975 5.147 3.74e-07 ***
## sectorconstruction 0.04826 0.10940 0.441 0.65930
## sectorother -0.12610 0.06063 -2.080 0.03802 *
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.4793 on 526 degrees of freedom
## Multiple R-squared: 0.1861, Adjusted R-squared: 0.1753
## F-statistic: 17.18 on 7 and 526 DF, p-value: < 2.2e-16
複数の変数の交互作用もモデルに投入できる。x と y という変数の交互作用項をモデルに投入するには、独立変数を
x * y
とすれば主効果と交互作用効果がモデルに投入される。例えば以下のように。
lm5 <- lm(wage ~ gender * experience, data = CPS1985)
さらに高次の交互作用を指定するには、“x * y * z” のようにすればよい。
複数の回帰分析の結果をまとめて表にするには、memisc パッケージの mtable( ) 関数や texreg パッケージの screenreg() 関数など、いくつかの関数がいくつかのパッケージで提供されている。
mtable(回帰分析の結果1, 回帰分析の結果2, 回帰分析の結果3, …)
screenreg(list(回帰分析の結果1, 回帰分析の結果2, 回帰分析の結果3, …))
例えば以下のように
library(memisc)
mtable(lm1, lm2, lm3)
##
## Calls:
## lm1: lm(formula = wage ~ age, data = CPS1985)
## lm2: lm(formula = wage ~ age + education + experience, data = CPS1985)
## lm3: lm(formula = wage ~ age + education + ethnicity, data = CPS1985)
##
## ==============================================================
## lm1 lm2 lm3
## --------------------------------------------------------------
## (Intercept) 6.167*** -4.770 -5.260***
## (0.723) (7.043) (1.308)
## age 0.078*** -0.022 0.105***
## (0.019) (1.155) (0.017)
## education 0.948 0.811***
## (1.155) (0.078)
## experience 0.128
## (1.156)
## ethnicity: hispanic/cauc -0.410
## (0.923)
## ethnicity: other/cauc -0.850
## (0.604)
## --------------------------------------------------------------
## R-squared 0.031 0.202 0.205
## N 534 534 534
## ==============================================================
## Significance: *** = p < 0.001; ** = p < 0.01; * = p < 0.05
library(texreg)
## Version: 1.38.6
## Date: 2022-04-06
## Author: Philip Leifeld (University of Essex)
##
## Consider submitting praise using the praise or praise_interactive functions.
## Please cite the JSS article in your publications -- see citation("texreg").
screenreg(list(lm1, lm2, lm3))
##
## ==================================================
## Model 1 Model 2 Model 3
## --------------------------------------------------
## (Intercept) 6.17 *** -4.77 -5.26 ***
## (0.72) (7.04) (1.31)
## age 0.08 *** -0.02 0.10 ***
## (0.02) (1.15) (0.02)
## education 0.95 0.81 ***
## (1.16) (0.08)
## experience 0.13
## (1.16)
## ethnicityhispanic -0.41
## (0.92)
## ethnicityother -0.85
## (0.60)
## --------------------------------------------------
## R^2 0.03 0.20 0.21
## Adj. R^2 0.03 0.20 0.20
## Num. obs. 534 534 534
## ==================================================
## *** p < 0.001; ** p < 0.01; * p < 0.05
複雑なモデルを推定した場合、推定結果の意味は係数を見ているだけではよくわからない場合がある。その場合、モデルからの予測値をプロットするとわかりやすい。
pred(回帰分析の結果、予測値を出したい独立変数の値を入力したデータフレーム)
必ず「予測値を出したい独立変数の値を入力したデータフレーム」を作らなければならないので、自分がどんな予測値をプロットしたいのか、よく考える必要がある。例えば、先ほどの age の二乗項を投入した分析結果から予測される18から64歳までの賃金をプロットしたいとしよう。その場合、まずは以下のように計算し、プロットする。
data.for.pred <- data.frame(age = 18 : 64) # 年齢の最小値と最大値の範囲で指定
head(data.for.pred) # 作ったデータフレームの中身を確認
## age
## 1 18
## 2 19
## 3 20
## 4 21
## 5 22
## 6 23
pred1 <- predict(lm4, data.for.pred)
plot(18 : 64, pred1, type = "l") # type = "l" は点をプロットするのではなく線を描けという指定
gender と experience の交互作用を推定したモデル (lm5 と名づけた)の予測値をプロットしたいとしよう。この場合、男女それぞれの労働経験年数に対応する賃金の予測値をプロットしたいのだから、プロットしたい性別 (gender) と労働経験年数 (experience) の組み合わせをすべて持つデータフレームをあらかじめ作ってやる必要がある。以下のスクリプトがそれである。
data.for.pred2 <- data.frame(
experience = rep(0 : 55, 2), # 0~55 の数値を2回繰り返すベクトル
gender = gl(2, 56, labels = c("male", "female") # male を 56回、次に female を 56回繰り返す因子
)
)
head(data.for.pred2)
## experience gender
## 1 0 male
## 2 1 male
## 3 2 male
## 4 3 male
## 5 4 male
## 6 5 male
pred2 <- predict(lm5, data.for.pred2)
plot(
x = data.for.pred2$ experience,
y = pred2,
pch = 19,
xlab = "労働経験年数",
ylab = "予測される賃金"
)
text(25, c(8.2, 11), c("女性", "男性")) # text() は図に文字を書き加えるための関数
説明変数はたくさんあるが、特に興味のある変数によって予測値がどう変化するかだけプロットしたい場合もある。しかし、pred() 関数には、必ずモデルに投入したすべての独立変数を含むデータフレームを指定してやる必要があるので少し工夫が必要である。以下の例を見よ。
lm6 <- lm(wage ~ age + I(age^2) + education + occupation, data = CPS1985)
data.for.pred3 <- data.frame(
age = 18 : 64, # 年齢だけ 18~64歳まで変化させる
education = mean(CPS1985$ education), # 学歴は平均教育年数で固定
occupation = "worker" # 職種も worker に固定
)
head(data.for.pred3)
## age education occupation
## 1 18 13.01873 worker
## 2 19 13.01873 worker
## 3 20 13.01873 worker
## 4 21 13.01873 worker
## 5 22 13.01873 worker
## 6 23 13.01873 worker
pred3 <- predict(lm6, data.for.pred3)
plot(18 : 64, pred3, type = "l", xlab = "年齢", ylab = "モデルから予測される賃金")
上の例は、年齢 (age) の効果を図示しようとしているが、モデルからの予測値を計算するためには年齢だけではなく、教育年数と職業の値も指定してやる必要がある。そこで、教育年数には教育年数の平均値を、職業は最頻値の “worker” を一律に指定している。
分散分析は lm() で引数をカテゴリカル変数にすればできるが、まれに伝統的な分散分析表を出力したい場合がある。その場合、aov() という関数を使う。書式は lm とだいたい同じである。以下は使用例
aov1 <- aov(wage ~ gender, data = CPS1985)
summary(aov1)
## Df Sum Sq Mean Sq F value Pr(>F)
## gender 1 594 593.7 23.43 1.7e-06 ***
## Residuals 532 13483 25.3
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
回帰分析の際には、モデルの診断は重要である。モデルの診断とは、回帰分析が満たすべき条件を、データやモデルが本当に満たしているのか検討することである。論文などにはモデルの診断の結果は示されないことが多いので、軽視されがちであるが、誤った分析を避ける上で非常に重要である。ふつうは以下の点をチェックする。
モデルの特定とは、独立変数と従属変数にどのような関係があるのか特定(仮定)することである。例えば、本当は曲線的な関係なのに線形の関係を仮定していないか、本当は交互作用効果があるのにそれを見落としていないか、除去したり追加したりすべき独立変数はないか、従属変数は対数変換などする必要はないか、といった点を検討する。
残差が正規分布していないと、回帰分析の結果は最尤推定値にならない。最尤推定値でなくても Best Linear Unbiased Estimation (BLUE) であることには変わりないので、必ずしも深刻に受け止める必要はないが、従属変数の対数変換などでモデルの適合度を下げずに正規分布に近づけることができる場合もあるので、その場合は対数変換などを検討すると良い。
回帰分析では、残差の分散は独立変数の値とは独立で、一定であることが仮定されている。この仮定が満たされないと標準誤差を過小に推定してしまう。このような場合は、ロバスト標準誤差が計算されることが多い。
時系列データの場合や地域データの場合、残差が相関していることがある。また、横断調査のデータであっても、同じグループに属する対象者が近い残差を取ることがあり(マルチレベル・データ)、このような場合は、残差が独立とは言えず、やはり標準誤差が過小に推定されてしまうことが多い。時系列データや地域データ、マルチレベル・データの分析はここでは取り扱わない。診断法についてもこれらの分析法の解説をあたれ。
共線性とは、重回帰分析において、ある独立変数がその他の独立変数によって予測できてしまうことを言う。例えば、横断データで出生年と年齢を独立変数としてモデルに投入する場合、両者には共線性が生じる。なぜなら、\(\mathrm{調査年} - \mathrm{年齢} = \mathrm{出生年}\) という関係がほぼ成り立つので、誕生日が調査時点の前か後かによって多少のズレはあるが、出生年がわかれば調査時点での年齢もほぼわかる。このような場合、調査年と年齢の傾きの標準誤差は非常に大きくなり、推定結果も 1, 2 の事例を取り除いただけで大きく変化してしまうほど不安定になる。多重共線性とは、共線性が 3変数以上の変数のあいだに生じている状態である。例えば、夫婦二人だけの世帯の調査で、夫収入、妻収入、世帯収入を独立変数とした回帰分析をしたいとしよう。\(\mathrm{夫収入} + \mathrm{妻収入} = \mathrm{世帯収入}\)