2013年2月8日金曜日

【統計】【R】データセットをwide形式からlong形式に変換する

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:列名を分ける記号の指定

たとえば

  1. b2_01、b2_02、b2_03
  2. b1、b2、 b3
  3. 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を参照してください。

応援よろしくです。

0 件のコメント:

コメントを投稿