次元の海で溺れる

Rとデータ解析と統計手法たちとわたし

【reshape2,tidyr】 豆について考える(番外編)~溶けるの概念を見失った時のためのメモ~

前回の記事を書いていて、
2年前に

「reshape2::meltってなんだ。そもそもmeltってなんだ、溶けるってなんだ」

という、鳥はなぜ空を飛ぶの的な疑問に直面してたのを思い出したので、自分用メモ。

溶かすとは

当時釈然としてなかったのは、reshape2::meltを「えくせる的な行列入れ替え」と解釈していたことに端を発する。

◎えくせる的な行列入れ替え

f:id:WAFkw:20160121233012p:plain

◎reshape2::meltでの変換

f:id:WAFkw:20160121233133p:plain

・・・ちがうじゃんと。
思ってたのと違うじゃんと。

こんな変換誰が使うんだよと。 (cv.2年前わたし)

ということで、

そんな愚かな過去の自分に
使いどころと使い方と、tidyr::gatherとの微妙な表記の違いを捧げて、
反省してもらおうとおもいます。

題材

前回使った豆。
(引用:農林水産省/大豆関連データ集

> mameused_xts<- mameused
> mameused_xts$<- mameused$+1988 #西暦変換
> knitr::kable(mameused_xts)


||| みそ| しょうゆ| 豆腐.油揚| 納豆| 凍豆腐| 豆乳| 煮豆.惣菜| きな粉| その他|
|----:|:-----|----:|--------:|---------:|----:|------:|----:|---------:|------:|------:|
| 1997|1,019 |  165|       26|       494|  122|     30|    3|        33|     14|    132|
| 1998|1,046 |  162|       26|       495|  128|     30|    4|        33|     16|    152|
| 1999|1,017 |  166|       30|       492|  127|     29|    6|        33|     17|    117|
| 2000|1,010 |  166|       30|       492|  122|     29|    7|        33|     17|    114|
| 2001|1,015 |  149|       32|       492|  129|     29|    9|        33|     17|    125|
| 2002|1,035 |  149|       35|       494|  141|     29|   11|        33|     17|    126|
| 2003|1,034 |  138|       38|       494|  137|     30|   19|        33|     17|    128|
| 2004|1,053 |  139|       37|       496|  139|     33|   29|        33|     18|    129|
| 2005|1,052 |  141|       40|       494|  131|     33|   32|        33|     18|    130|
| 2006|1,046 |  140|       40|       492|  130|     33|   30|        33|     18|    130|
| 2007|1,045 |  139|       40|       497|  130|     30|   25|        33|     19|    132|
| 2008|1,037 |  137|       39|       496|  129|     29|   25|        33|     19|    130|
| 2009|993   |  131|       39|       490|  125|     27|   29|        33|     19|    100|
| 2010|976   |  127|       39|       480|  123|     26|   32|        33|     19|     97|
| 2011|950   |  126|       35|       465|  122|     24|   34|        31|     18|     95|
| 2012|932   |  124|       33|       450|  123|     22|   40|        30|     17|     93|
| 2013|936   |  123|       33|       454|  125|     20|   40|        30|     18|     93|
| 2014|942   |  133|       33|       447|  125|     19|   43|        30|     18|     94|

使いどころ

こちらも前回の話だけど、
上記データの状態から積み上げ棒グラフを書きたいと思ったとき。

f:id:WAFkw:20160101040839p:plain

考えるのは、

・列名をFactor型にしたらできそう
・じゃあ縦型データじゃないとダメじゃない?
・でも年の列はそのままがよくない?

みたいなこと。

その処理をやるのに
reshape2::meltとかtidyr::gatherとかを使ってます。

もっとオサレな用途もあるにちがいない....例え出てこないけど...

いざ変換

前回やったのはこんな感じ。
id引数に年を指定して、それ以外を縦持ちに変換した。

> mameused_xts<-reshape2::melt(mameused_xts,id="年")  #idを指定
> knitr::kable(head(subset(mameused_xts,mameused_xts$variable!="計") ,20))


|   ||variable |value |
|:--|----:|:--------|:-----|
|19 | 1997|みそ     |165   |
|20 | 1998|みそ     |162   |
|21 | 1999|みそ     |166   |
|22 | 2000|みそ     |166   |
|23 | 2001|みそ     |149   |
|24 | 2002|みそ     |149   |
|25 | 2003|みそ     |138   |
|26 | 2004|みそ     |139   |
|27 | 2005|みそ     |141   |
|28 | 2006|みそ     |140   |
|29 | 2007|みそ     |139   |
|30 | 2008|みそ     |137   |
|31 | 2009|みそ     |131   |
|32 | 2010|みそ     |127   |
|33 | 2011|みそ     |126   |
|34 | 2012|みそ     |124   |
|35 | 2013|みそ     |123   |
|36 | 2014|みそ     |133   |
|37 | 1997|しょうゆ |26    |
|38 | 1998|しょうゆ |26    |

ここから何パターンかやる。

idを明示的に指定しない

> #idを明示的に指定しない(計が使われる)
> mameused_2<-reshape2::melt(mameused_xts)
Using 計 as id variables
> knitr::kable(head(mameused_2,20))


||variable | value|
|:-----|:--------|-----:|
|1,019 ||  1997|
|1,046 ||  1998|
|1,017 ||  1999|
|1,010 ||  2000|
|1,015 ||  2001|
|1,035 ||  2002|
|1,034 ||  2003|
|1,053 ||  2004|
|1,052 ||  2005|
|1,046 ||  2006|
|1,045 ||  2007|
|1,037 ||  2008|
|993   ||  2009|
|976   ||  2010|
|950   ||  2011|
|932   ||  2012|
|936   ||  2013|
|942   ||  2014|
|1,019 |みそ     |   165|
|1,046 |みそ     |   162|

年まで容赦なく溶かされる。これは何を基準にidを選んでるんだろう。

複数のidを指定

> mameused_2<-reshape2::melt(mameused_xts,id=c("年","計")) #idを複数指定
> knitr::kable(head(mameused_2,20))


|||variable | value|
|----:|:-----|:--------|-----:|
| 1997|1,019 |みそ     |   165|
| 1998|1,046 |みそ     |   162|
| 1999|1,017 |みそ     |   166|
| 2000|1,010 |みそ     |   166|
| 2001|1,015 |みそ     |   149|
| 2002|1,035 |みそ     |   149|
| 2003|1,034 |みそ     |   138|
| 2004|1,053 |みそ     |   139|
| 2005|1,052 |みそ     |   141|
| 2006|1,046 |みそ     |   140|
| 2007|1,045 |みそ     |   139|
| 2008|1,037 |みそ     |   137|
| 2009|993   |みそ     |   131|
| 2010|976   |みそ     |   127|
| 2011|950   |みそ     |   126|
| 2012|932   |みそ     |   124|
| 2013|936   |みそ     |   123|
| 2014|942   |みそ     |   133|
| 1997|1,019 |しょうゆ |    26|
| 1998|1,046 |しょうゆ |    26|

年と計の列をそのままに変換できる。

時代はtidyr::gatherらしい

meltを長々と語ってるけど、
reshape2パッケージの進化版の時代に突入してしまっているので、
そちらについてもやる。

id一つ指定の時と同じ変換

> mameused_2<-tidyr::gather(mameused_xts,key=variable,value=value,-)
> knitr::kable(head(mameused_2,20))


||variable |value |
|----:|:--------|:-----|
| 1997||1,019 |
| 1998||1,046 |
| 1999||1,017 |
| 2000||1,010 |
| 2001||1,015 |
| 2002||1,035 |
| 2003||1,034 |
| 2004||1,053 |
| 2005||1,052 |
| 2006||1,046 |
| 2007||1,045 |
| 2008||1,037 |
| 2009||993   |
| 2010||976   |
| 2011||950   |
| 2012||932   |
| 2013||936   |
| 2014||942   |
| 1997|みそ     |165   |
| 1998|みそ     |162   |

引数がびみょうに違う。
meltがidに「残したい列(名)を指定」だったのに
gatherは「溶かしたい列名を指定」なので、残したい列は「-」マイナスを付けて除外指定をする。

keyとvalueには変換後の列名を指定する。

idの複数指定

> mameused_2<-tidyr::gather(mameused,key,value,-,-) #溶かさないものはマイナス指定
> knitr::kable(head(mameused_2,20))


|||key      | value|
|--:|:-----|:--------|-----:|
|  9|1,019 |みそ     |   165|
| 10|1,046 |みそ     |   162|
| 11|1,017 |みそ     |   166|
| 12|1,010 |みそ     |   166|
| 13|1,015 |みそ     |   149|
| 14|1,035 |みそ     |   149|
| 15|1,034 |みそ     |   138|
| 16|1,053 |みそ     |   139|
| 17|1,052 |みそ     |   141|
| 18|1,046 |みそ     |   140|
| 19|1,045 |みそ     |   139|
| 20|1,037 |みそ     |   137|
| 21|993   |みそ     |   131|
| 22|976   |みそ     |   127|
| 23|950   |みそ     |   126|
| 24|932   |みそ     |   124|
| 25|936   |みそ     |   123|
| 26|942   |みそ     |   133|
|  9|1,019 |しょうゆ |    26|
| 10|1,046 |しょうゆ |    26|

溶かしたくない列を複数指定する時はカンマで区切っちゃってOK。
meltでid=c("年","計")ってした時と同じ結果になる。

おまけ

上記でやってないけど、
data引数はパイプで渡しちゃうのが正なのでしょう。

> mameused_xts %>%
+ tidyr::gather(key,value,-)->mameused_2
> knitr::kable(head(mameused_2,20))

||key  |value |
|----:|:----|:-----|
| 1997||1,019 |
| 1998||1,046 |
| 1999||1,017 |
| 2000||1,010 |
| 2001||1,015 |
| 2002||1,035 |
| 2003||1,034 |
| 2004||1,053 |
| 2005||1,052 |
| 2006||1,046 |
| 2007||1,045 |
| 2008||1,037 |
| 2009||993   |
| 2010||976   |
| 2011||950   |
| 2012||932   |
| 2013||936   |
| 2014||942   |
| 1997|みそ |165   |
| 1998|みそ |162   |

おわり

完全に備忘録。

もうすぐの誕生日、忘れっぱなしでいったら年取らないで済むかなあ