data.frame を ggplot2 用に加工する

f:id:joker1110:20120217070139p:image:w360

背景

ggplot2でデータを図示するとき,data.frame()の形にしておくことが必須!
でも,巷に存在するデータは必ずしも適したdata.frame()の形になっていない.
このような統計データが巷には多く存在する.横軸に時間,縦軸にカテゴリである.

> sdata <- read.csv("reshape_data.csv",header=T)
> sdata
   X            X2003        X2004          X2005          X2006          X2007          X2008
1 A 0.639303353 0.1606200 0.49761181 0.05821738 0.28906559 0.86778986
2 B 0.151501818 0.9834539 0.73344139 0.89570543 0.40995754 0.02346937
3 C 0.003360582 0.8289247 0.84555681 0.88112286 0.03419304 0.59529404
4 D 0.923997222 0.5709377 0.01070927 0.34586471 0.95764872 0.89591526

目的

ggplot2に適した形にするには,時間列を作り,そこに時間値を書き込みたいわけだ.
つまり,こんな感じ

   name  time                    X id
1       A 2003 0.639303353  1
2       B 2003 0.151501818  2
3       C 2003 0.003360582  3
4       D 2003 0.923997222  4
1       A 2004 0.160620002  1
2       B 2004 0.983453932  2
3       C 2004 0.828924747  3
4       D 2004 0.570937680  4
1       A 2005 0.497611813  1
2       B 2005 0.733441391  2
3       C 2005 0.845556813  3

できる限り簡単に,ggplot2に適したdata.frame()の形にしたい.

手段

reshape()を利用する。(追記にmelt.data.frameを利用した簡単な方法があります。推奨。)

実験

まず,時系列を表す列名を「キー.数字」または「キー.文字列」のようにキーで表す.たとえば,

> sname <- c("X.2003","X.2004","X.2005","X.2006","X.2007","X.2008")

のように時間で表したい文字列を作成しておく.
次に,データの列名を変更.

> names(sdata) <- c("name",sname)
> sdata
  name      X.2003    X.2004     X.2005     X.2006     X.2007     X.2008
1    A 0.639303353 0.1606200 0.49761181 0.05821738 0.28906559 0.86778986
2    B 0.151501818 0.9834539 0.73344139 0.89570543 0.40995754 0.02346937
3    C 0.003360582 0.8289247 0.84555681 0.88112286 0.03419304 0.59529404
4    D 0.923997222 0.5709377 0.01070927 0.34586471 0.95764872 0.89591526

これで準備はできた.あとはreshape()するだけ.

> sdata <- reshape(sdata, direction="long", varying=sname)
> sdata
       name time           X id
1.2003    A 2003 0.639303353  1
2.2003    B 2003 0.151501818  2
3.2003    C 2003 0.003360582  3
4.2003    D 2003 0.923997222  4
1.2004    A 2004 0.160620002  1
2.2004    B 2004 0.983453932  2
3.2004    C 2004 0.828924747  3
4.2004    D 2004 0.570937680  4
1.2005    A 2005 0.497611813  1

完成!列名timeに時間が入っている.ただidという列が付加されちゃうのはなぜ??

結論

reshape()することで,横長のデータ(横軸に時系列)を縦長のデータ(時間を列に収納したもの)に簡単に変更可能.
ただ,もとの列名にidという名前を入れるとエラーになるようです.

追記

もっと簡単な方法があった.melt.data.frame()を利用する方法.

> sdata <- read.csv("reshape_data.csv",header=T)
> sdata
   X            X2003        X2004          X2005          X2006          X2007          X2008
1 A 0.639303353 0.1606200 0.49761181 0.05821738 0.28906559 0.86778986
2 B 0.151501818 0.9834539 0.73344139 0.89570543 0.40995754 0.02346937
3 C 0.003360582 0.8289247 0.84555681 0.88112286 0.03419304 0.59529404
4 D 0.923997222 0.5709377 0.01070927 0.34586471 0.95764872 0.89591526

に対して

> sdata <- melt.data.frame(sdata,id.vars="X",variable_name="year")
> sdata
   X  year       value
1  A X2003 0.639303353
2  B X2003 0.151501818
3  C X2003 0.003360582
4  D X2003 0.923997222
5  A X2004 0.160620002
6  B X2004 0.983453932
7  C X2004 0.828924747
8  D X2004 0.570937680
9  A X2005 0.497611813
10 B X2005 0.733441391
11 C X2005 0.845556813
12 D X2005 0.010709274
13 A X2006 0.058217382
14 B X2006 0.895705435
15 C X2006 0.881122858
16 D X2006 0.345864708
17 A X2007 0.289065585
18 B X2007 0.409957539
19 C X2007 0.034193039
20 D X2007 0.957648725
21 A X2008 0.867789855
22 B X2008 0.023469369
23 C X2008 0.595294041
24 D X2008 0.895915255

一行で書けた.