R-bloggerで
Converting a dataset from wide to long(データセットをwide形式からlong形式に変換)という記事が投稿されていました。以下は、その記事をまとめたものです。
この記事の要旨は、
Rのreshape関数を使って、wide形式のデータをlong形式のデータに変換する
ということです。
wide形式とは、複数の個体のデータ系列が横方向に接続されたデータで、例えば以下のようなデータセットのことを言います。
> births.wide
caseid v012 b2_01 b2_02 b2_03 b4_01 b4_02 b4_03
1 1 30 2000 2005 NA 1 1 NA
2 2 29 2001 2010 NA 1 2 NA
3 3 32 1999 2002 2006 1 1 1
4 4 35 1999 2009 NA 2 1 NA
5 5 34 1998 NA NA 2 NA NA
6 6 23 NA NA NA NA NA NA
7 7 25 2000 NA NA 1 NA NA
>
v012は母親の年齢を表している列です。b2は子どもが生まれた年が記入されていて、b2_01は1人目の子どもが、b2_02は2人目の子どもが、b2_03は3人目の子ども生まれた年を表しています。b4は子どもの性別を表していて、先ほどと同様に、b4_01は1人目の子どもの、b4_02は2人目の子どもの、b4_03は3人目の子どもの性別を表しています。欠損値は子どもがいないことを示しています。たとえば、最初の被験者(caseid=1)の年齢は30で、子どもが2人おり、最初の子どもは2000年に、二番目の子どもは2005年に生まれたことがわかります。3人目は生まれていないので、b2_03とb4_03は欠損値になっています。
このデータをRのreshape関数を使って、long形式(複数の個体のデータの集合が縦方向に接続されたデータ)に変換します。
reshape(data, varying = NULL,
timevar = "time", idvar = "id", direction, sep = "")
- data:変換したいデータフレームの指定
- varying:long形式の列と対応するwide形式の列を指定
- timevar:指定された変数をwideあるいはlongに変換する際に、その順序を指定
- idvar:同じ被験者を表すデータフレーム中の変数の指定
- direction:wide形式かlong形式にするかの指定
- sep:列名を分ける記号の指定
たとえば
- b2_01、b2_02、b2_03
- b1、b2、 b3
- year.1、 year.2、 year.3
という複数の列をそれぞれ一つにまとめたい場合を考えます。
第一に、b2_01、b2_02、b2_03を一つの列に変換したい場合、sep="_"を指定します。
第二に、b1、b2、 b3という列を一つの列に変換したい場合、sep=""には何も指定しません。
第三に、year.1、 year.2、 year.3という列を一つの列に変換したい場合はsep="."を指定します。
それでは先ほどのbirths.wideをlong形式に変換します。
> births.long1 <- reshape(births.wide, varying=c("b2_01","b2_02","b2_03", "b4_01", "b4_02", "b4_03"), direction="long", idvar="caseid", sep="_")
> births.long1
caseid v012 time b2 b4
1.1 1 30 1 2000 1
2.1 2 29 1 2001 1
3.1 3 32 1 1999 1
4.1 4 35 1 1999 2
5.1 5 34 1 1998 2
6.1 6 23 1 NA NA
7.1 7 25 1 2000 1
1.2 1 30 2 2005 1
2.2 2 29 2 2010 2
3.2 3 32 2 2002 1
4.2 4 35 2 2009 1
5.2 5 34 2 NA NA
6.2 6 23 2 NA NA
7.2 7 25 2 NA NA
1.3 1 30 3 NA NA
2.3 2 29 3 NA NA
3.3 3 32 3 2006 1
4.3 4 35 3 NA NA
5.3 5 34 3 NA NA
6.3 6 23 3 NA NA
7.3 7 25 3 NA NA
>
これで、long形式に変換できていますが、被験者順で並び替えるにはorder関数を使うと上手くいきます。
> births.long2 <- reshape(births.wide, varying=c(3:8), direction="long", idvar="caseid", sep="_")
> births.long2<-births.long2[order(births.long2$caseid),]
> births.long2
caseid v012 time b2 b4
1.1 1 30 1 2000 1
1.2 1 30 2 2005 1
1.3 1 30 3 NA NA
2.1 2 29 1 2001 1
2.2 2 29 2 2010 2
2.3 2 29 3 NA NA
3.1 3 32 1 1999 1
3.2 3 32 2 2002 1
3.3 3 32 3 2006 1
4.1 4 35 1 1999 2
4.2 4 35 2 2009 1
4.3 4 35 3 NA NA
5.1 5 34 1 1998 2
5.2 5 34 2 NA NA
5.3 5 34 3 NA NA
6.1 6 23 1 NA NA
6.2 6 23 2 NA NA
6.3 6 23 3 NA NA
7.1 7 25 1 2000 1
7.2 7 25 2 NA NA
7.3 7 25 3 NA NA
これで被験者順に並び替えることができました。わかりやすく名前を付け替えるなら
names(births.long2) <- c("subject","age","order", "birthyear", "childsex")
で、欠損値を除くには
births.long2<-na.omit(births.long2)
と入力すればオッケーです。
詳細は、
Converting a dataset from wide to longを参照してください。
応援よろしくです。