<- c(1, 2, 3, 2, 2, 1, 1, 2, 1, 3) q01
超初心者向けのRガイド
c. 欠損値,変数のリコード
1 全体の構成
2 変数(variable)と変数値(value)
社会調査データを扱う場合に実際に面倒なのは,データ分析や多変量解析のくだりではなく,むしろその準備作業としてのデータの整備や加工の部分である。
収集した情報(調査票の回答選択肢番号)から別の数値に割り当てるリコードや,情報が得られなかった場合の欠損値の処理などがきちんと出来ないと,そもそも適切な集計や分析が行えない。
しかしこれらの作業は取り分け統計ソフトによって異なる部分であり,特にRの場合にはSPSSなどとやや発想を変えなければうまく使えない事も多い。
2.1 変数の種類: 数値型と要因型
心理統計学では変数の種類(尺度水準)を,名義尺度,順序尺度,間隔尺度,比例尺度に分ける事が多い(『入門・社会統計学』1-1)。名義尺度や順序尺度の情報を数値で表現する事は多いが,足し算や引き算などの演算が出来るのは間隔尺度と比例尺度である。
他方,SPSSなどの統計ソフトをはじめ,コンピュータソフトは一般的に,数値型/文字型の様に情報を区別し,数値型と認識されたものには加減乗除などの演算を行う。数字でさえあれば,それが名義尺度であるか順序尺度であるか間隔尺度以上であるかは問題としない。
コンピュータソフトを用いて統計分析を行う場合,変数の種類或いは尺度水準を正しく理解して区別しないと,名義尺度や順序尺度について算術平均を計算するなど,気付かないうちに誤った分析をしてしまう事になるので,この点についてよく注意しなければならない。
Rでは取り敢えず,数値型numeric,文字型character,要因型factorの3つの区別に注意する事にしよう1。
例えば,社会調査で性別を訪ねて,男性=1,女性=2,その他=3として回答を収集したとしよう。これは,文字で表現しようが数字で表現しようが,名義尺度である。
要因型変数は名義尺度として扱われる。名義尺度や順序尺度のカテゴリカル変数を分析する際には,きちんと要因型の”factor”になっているかどうかを確認し,“numeric”になっていれば上の様に”factorに”変換した新変数を作成してから分析に用いよう。
調査データの回答結果は通常,選択肢番号などの数値で記録されている。
しかしそれがカテゴリカル変数であるならば,以下の様にして要因型変数も同時に作成しておき,都合に応じてそのいずれかを用いるのが便利である。
<- factor(q01, levels = 1:3, labels = c("男性", "女性", "その他"))
Q01 summary(Q01)
男性 女性 その他
4 4 2
class(Q01)
[1] "factor"
table(q01, Q01)
Q01
q01 男性 女性 その他
1 4 0 0
2 0 4 0
3 0 0 2
2.2 欠損値(NA)
社会調査では,情報を得ようとしても得られない場合が多々ある。得られなかった情報を「欠損」や「欠測」,missing value, nonresponse(item nonresponse, unit nonresponse) と呼ぶ。
MS-Excelやcsvでデータ・ファイルを作成する際,欠損値には,予め決めておいたルールに従って9や99を入力したり,単に空欄にしておいたりする。
9や99などの数値が入力されている場合は,それを読み込んで作成されたRのデータ・フレイムでも9や99として他の数値と同様に扱われる。特にそれが欠損値を意味すると云う事は考慮されないので注意が必要である。
csvファイルで空欄になっているセルについては,Rでの欠損値を意味する NA としてデータ・フレイムに読み込まれる。
9や99として読み込まれると,うっかり有効なデータだとして計算に含まれたりするので注意が必要であり,NAとして読み込まれると,うっかり有効扱いにされる事は無いが,逆に関数が意図した計算結果を返さない事があったりして面倒である。
次の様に,最後の欠損値の部分だけが異なる二つのヴェクトルで試してみよう。summary(q06a)とsummary(q06b)の結果を見比べると,q06aは其の儘で使用出来ない事が分かる。
<- c(12, 12, 14, 18, 16, 16, 9, 16, 12, 16, 99)
q06a <- c(12, 12, 14, 18, 16, 16, 9, 16, 12, 16, NA)
q06b summary(q06a); summary(q06b)
Min. 1st Qu. Median Mean 3rd Qu. Max.
9.00 12.00 16.00 21.82 16.00 99.00
Min. 1st Qu. Median Mean 3rd Qu. Max. NA's
9.0 12.0 15.0 14.1 16.0 18.0 1
しかし,q06bは,summary( )関数では問題を生じないが,mean( ) や sd( ) と云った基本的な関数で,其の儘では計算を拒否されてしまう。いずれも,結果が NA で返ってきてしまう。
mean(q06b); sd(q06b); var(q06b)
[1] NA
[1] NA
[1] NA
これを防ぐには,mean(q06b, na.rm=T) や sd(q06b, na.rm=T) の様に,na.rm = T と云うオプションを追加しなければならない。
mean(q06b, na.rm = T); sd(q06b, na.rm = T); var(q06b, na.rm = T)
[1] 14.1
[1] 2.766867
[1] 7.655556
また,度数分布表を作成しようと table(q06b) とすると今度はNAが自動的に除外されて出力されるが,これでは NA が存在するのかどうか分からない。
データやファイルのチェック作業などでは,欠損値を含んで度数分布表や分割表(クロス表)を作成しなければならない。
この場合は table(q06b, useNA = “always”) 又は table(q06b, useNA = “ifany”) としなければならない。
useNA = のオプションを省略した場合は自動的に useNA = “no” として扱われているのである。
table(q06b)
q06b
9 12 14 16 18
1 3 1 4 1
table(q06b, useNA = "always")
q06b
9 12 14 16 18 <NA>
1 3 1 4 1 1
table(q06b, useNA = "ifany")
q06b
9 12 14 16 18 <NA>
1 3 1 4 1 1
table(q06b, useNA = "no")
q06b
9 12 14 16 18
1 3 1 4 1
その他,相関係数を求める関数 cor( ) も,NAが含まれていると計算してくれないので,cor(x, y , use = “complete”) の様に,use = “complete”もしくはuse = “pairwise”のオプションを指定しなければならない。
同じ相関係数でも,検定や区間推定を同時に行う cor.test( ) は自動的にNAを除外して計算する。
<- c(400, NA, 600, 1000, 1500, 700, 200, 500, 800, 900, NA)
q07b
cor(q06b, q07b)
[1] NA
cor(q06b, q07b , use="complete")
[1] 0.6499337
cor.test(q06b, q07b)
Pearson's product-moment correlation
data: q06b and q07b
t = 2.2626, df = 7, p-value = 0.05811
alternative hypothesis: true correlation is not equal to 0
95 percent confidence interval:
-0.02496288 0.91787036
sample estimates:
cor
0.6499337
データ集計や分析で何故か計算結果が NA として返される場合には,データの中にNAが含まれているのに適切にそれを除外していない可能性を考えて見よう。
また table( ) を使用する時には,useNA = “always”のオプションを付けた場合と見比べて,NAの有無を確認する様にしよう。
欠損値を処理するオプションの指定の仕方は関数によって異なっている事もあるので,知っているオプションでうまく行かない場合にはウェブなどで調べてみよう。
3 リコード,変数の加工
社会調査では回答選択肢の数字を其の儘データファイルに記録するのが通例だが,回答選択肢番号が分析可能な数量変数になるとは限らない。
例えば,最終学歴schoolが「中学=1,高校=2,短期大学=3,高等専門学校=4,四年制大学=5,大学院=6」として記録されている場合,これを教育年数(それぞれ,9,12,14,14,16,18)として分析に用いたい事が多い。
仮に10人分のデータ school <- c(3, 5, 2, 6, 5, 2, 4, 3, 1, 5, 4) であるとしよう。
SPSSであれば recode と云うコマンドを使うが,Rに同じものは無い。どんなコンピュータ言語にもあるif文と云うのを使う方法もあるが,schoolはあくまで一つの数字ではなくヴェクトルである事をきちんと理解していないと,意図した動作をしない。
3.1 if( )を用いたrecode
「schoolが1ならばeduを9にする」を其の儘コマンドに表現すると, if (school == 1) edu <- 9 となりそうだが,school == 1 はschoolが(長さのあるヴェクトルでなく)一つの数字であるように想定している表現となっておりうまく行かない。
表示されるエラーメッセイジと edu の内容を確認すれば分かる。
<- c(3, 5, 2, 6, 5, 2, 4, 3, 1, 5, 4) # 変換の元の変数
school <- NULL # 新変数の初期化。
edu
if (school == 1) edu <- 9
Error in if (school == 1) edu <- 9: the condition has length > 1
edu
NULL
school自体はヴェクトルであり,その中の要素が1に等しいか否かを評価したいので,以下の様にすると意図した結果になる。
== 1] <- 9
edu[school edu
[1] NA NA NA NA NA NA NA NA 9 NA NA
[ ] はヴェクトル中の要素を指定する為のものであった。
この [ ] の中に書いてあるものは要素についての条件であると解釈され,“schoolの値が1であるケース(行)についてはeduの値に9を代入せよ”と云う意味になる。
但しこの場合,既にeduと云うヴェクトルが存在している事を前提とした表現になるので,先にeduを空箱(NULL)として作成しておく。
作成されたeduを確認すると一ヵ所だけ9になっており,他はNAが代入されている。この方式で意図した変換は可能だが,schoolの全ての値について式を書かなければならないので手間がかかる。
3.2 ヴェクトルであることを使用した写像変換
もっと効率的な方法として,次の様な方法がある。
c(9, 12, 14, 16)はヴェクトルである。c(9, 12, 14, 16)の要素を指定したい場合(例えば2番目の要素である12),c(9, 12, 14, 16)[2]などとする事になる。
要素は複数を指定する事が出来るので,c(9, 12, 14, 16)[c(2, 3)]などとする事が出来る2。
schoolも一次元ヴェクトルであるので,こうしたヴェクトルの要素指定を応用してSPSSのrecode同様に(或いはより簡単に)新変数を作成する事が出来る。
c(9, 12, 14, 14, 16, 18) # vectorの確認
[1] 9 12 14 14 16 18
c(9, 12, 14, 14, 16, 18)[2] # vectorの[2番目]の要素を指定
[1] 12
<- c(9, 12, 14, 14, 16, 18)[school]
edu school
[1] 3 5 2 6 5 2 4 3 1 5 4
edu
[1] 14 16 12 18 16 12 14 14 9 16 14
新変数を作成したら,必ず以下の様に正しく作成されている事を確認する。
addmargins(table(school, edu, useNA = "always"))
edu
school 9 12 14 16 18 <NA> Sum
1 1 0 0 0 0 0 1
2 0 2 0 0 0 0 2
3 0 0 2 0 0 0 2
4 0 0 2 0 0 0 2
5 0 0 0 3 0 0 3
6 0 0 0 0 1 0 1
<NA> 0 0 0 0 0 0 0
Sum 1 2 4 3 1 0 11
3.3 ダミー変数
性別はよく「男性=1,女性=2」(調査によっては更に「その他=3」等がある)と記録されているが,俗に「男性ダミー」(或いは女性ダミー)と呼ばれる変数に変換したい事がしばしばある。
男性ダミー変数とは,男性であれば1,そうでなければ0の値をとる変数の事である。
変数sexは1(男性),2(女性),3(その他)の値を取るとすると,男性ダミーmaleは次の様に作成出来る。
<- c(1, 0, 0)[sex] male
女性ダミーなら female <- c(0, 1, 0)[sex]
である。
3.4 要因型変数への変換
上のshool変数を,初等学歴(義務教育)/中等学歴(高校)/高等学歴(短大以上)の3区分の名義尺度gakuに変換するには次の様に要因型(因子型)変数を作成すれば良い。
<- c(1, 2, 3, 3, 3, 3)[school]
gaku0 <- factor(gaku0, levels = 1:3, labels = c("初等", "中等", "高等"))
gaku gaku
[1] 高等 高等 中等 高等 高等 中等 高等 高等 初等 高等 <NA>
Levels: 初等 中等 高等
summary(gaku)
初等 中等 高等 NA's
1 2 7 1
addmargins(table(school, gaku, useNA = "ifany"))
gaku
school 初等 中等 高等 <NA> Sum
1 1 0 0 0 1
2 0 2 0 0 2
3 0 0 2 0 2
4 0 0 1 0 1
5 0 0 3 0 3
6 0 0 1 0 1
<NA> 0 0 0 1 1
Sum 1 2 7 1 11