Reshape2 : データ整形

Last Change: 14-Dec-2014.
author : qh73xe

このページでは R のデータ整形用パッケージである Reshape2 に関して記述していきます.

これは何?

このライブラリは R 界隈の神様と名高い, Hadley Wickham の作成したデータ整形用ライブラリです. 同氏の作成した plyr と機能的に似ている部分もあるのですが,あちらは変数自体の操作 を主眼にした機能が多いのに対し, reshape2 はデータの形式を変換することに機能の主眼をおいています.

reshape2 パッケージの出来ることは主に2つです.

  • melt : 横長に変数が入っているデータを縦長に変更する
  • (a | d) cast : 指定変数ごとに何らかの処理をした量を入れる

注釈

最近の動向

前述した Hadley Wickham 氏ですが最近は tidyr というライブラリを作成しています. このライブラリは plyr の後進である dplyr の書式に合わせて reshape2 を再編集したものです.

導入方法

install.packages("reshape2")

サンプルデータ

今回使用するデータはパッケージに付属する French fries というデータです. このデータは「時間経過をした場合のフライドポテトの味に対する油の効果の感覚実験」 のデータです.

Data.Frame の内容は以下の通りです.

  • ファクター
    • treatment: 油の種類 (3 種類)
    • rep: 異なる揚げ物鍋 (2 種類)
    • subject: 被験者 (12 名)
    • time: 異なる日付 (10 日)
  • 観測値
    • potato: ポテト臭
    • buttery: バター臭
    • grassy: 青臭さ
    • rancid: 悪臭
    • painty: ペンキ臭

とりあえず,head() でデータの数行を出してみます.

library("reshape2")
head(french_fries)
        time treatment subject rep potato buttery grassy rancid painty
61         1         1       3   1    2.9     0.0    0.0    0.0    5.5
25         1         1       3   2   14.0     0.0    0.0    1.1    0.0
62         1         1      10   1   11.0     6.4    0.0    0.0    0.0
26         1         1      10   2    9.9     5.9    2.9    2.2    0.0
63         1         1      15   1    1.2     0.1    0.0    1.1    5.1
27         1         1      15   2    8.8     3.0    3.6    1.5    2.3

melt

さて, french_fries のようなデータの形式はよくある書き方だと思います. しかし,このような書き方では,各観測値をまとめて処理したい場合 (例えば, french_fries を質問項目間で正規化したい場合など),スクリプト が冗長になってしまいがちです.

そのような際には質問項目のタイプの list と 観測値の list といったように管理をし たくなります.このように横長の Data.Frame を縦長に変更したい際に使用するのが melt 関数です.

ffm <- melt(french_fries, id = 1:4, na.rm = TRUE)
head(ffm)
  time treatment subject rep variable value
1    1         1       3   1   potato   2.9
2    1         1       3   2   potato  14.0
3    1         1      10   1   potato  11.0
4    1         1      10   2   potato   9.9
5    1         1      15   1   potato   1.2
6    1         1      15   2   potato   8.8

注釈

データテーブルの形式の変換

私の場合,このような処理を行う一番よくある例は ggplot2 を使用しているときです. 例えば french_fries でしたら, 各観測値別に分けた box plot をとりあえず plot したい場合はよくあるかと思います.

library("ggplot2")
ffm <- melt(french_fries, id = 1:4, na.rm = TRUE)
ggplot(ffm, aes(y=value, x=variable)) + geom_boxplot()

.. image:: fig/reshape2_1.png

cast

一旦 melt をしたデータは cast することも可能です. cast とはデータを任意の x 軸, y 軸ごとに,ある処理を加えたデータに加工する という意味です.ある処理を加える対象は当然,value になるはずです.

例えば,時間経過(time)を x 軸に,被験者(subject)を y 軸にとった際の value の 数のデータが欲しい際には以下のようにします.

>>> acast(ffm, subject ~ time, length)
   1   2  3  4  5  6  7  8   9  10
3  30  30 30 30 30 30 30 30 30   0
10 30  30 30 30 30 30 30 30 30  30
15 30  30 30 30 25 30 30 30 30  30
16 30  30 30 30 30 30 30 29 30  30
19 30  30 30 30 30 30 30 30 30  30
31 30  30 30 30 30 30 30 30  0  30
51 30  30 30 30 30 30 30 30 30  30
52 30  30 30 30 30 30 30 30 30  30
63 30  30 30 30 30 30 30 30 30  30
78 30  30 30 30 30 30 30 30 30  30
79 30  30 30 30 30 30 29 28 30   0
86 30  30 30 30 30 30 30 30  0  30

また,油の種類と質問項目別に value の平均値が見たい場合以下の通りです.

>>> dcast(ffm, treatment ~ variable, mean, margins = TRUE)
  treatment   potato  buttery    grassy   rancid   painty    (all)
1         1 6.887931 1.780087 0.6491379 4.065517 2.583621 3.194478
2         2 7.001724 1.973913 0.6629310 3.624569 2.455844 3.146413
3         3 6.967965 1.717749 0.6805195 3.866667 2.525541 3.151688
4     (all) 6.952518 1.823699 0.6641727 3.852230 2.521758 3.164218

その他

colsplit

colsplit 関数はある区切り文字を含む文字列のリストを, 区切り文字で分けたデータフレームに変更するための関数です.

例えば以下のような使用をします.

>>> x <- c("a_1", "a_2", "b_2", "c_3")
>>> vars <- colsplit(x, "_" , c("trt", "time"))
>>> str(vars)
'data.frame':  4 obs. of  2 variables:
 $trt : chr  "a" "a" "b" "c"
 $time: chr  "a" "a" "a" "a"