今までRでデータの変数名を変更したり条件でグループ化したりしました。






ここからは集計して平均や標準偏差などの要約を出したり、グラフを作るための準備に進みます。


こういったグラフを作るにはもう1つ工夫が必要です。

それはwideデータをlongデータに変更することです。

今回はlongデータとwideデータの違いを知り、longデータに変換するgather関数を紹介します。




1.wideデータとlongデータ

wideデータというのは1つのid(たとえば患者氏名)に対してデータが横に並びます。

スクリーンショット 2019-02-20 0.03.06
これはまた別の架空のデータです。4人にあるテストを3回ずつ行った設定です。

データを入力したり人の目で見る時はwideデータがわかりやすいです。

ただ今後出てくるのですが、Rではグラフを作るときに「『回数』で色分けして!」とか「『回数』で別々のグラフを作って」みたいな指定ができます。そのためにはlongデータが便利になります。


2.gather関数とspread関数

スクリーンショット 2019-02-20 0.53.33

wideをlongに変えるのがgather関数で、longをwideに戻すのがspread関数です。

ここで大切になるのがkey = と value=です。

key = も valueもlongデータの変数名に当たる部分です。wideデータにはそれに当てはまる名前を入れる欄がなく、列を分けることで表示しています。



3.gather関数の使い方

gather(使うデータ名, くっつける列, key = 要素の変数名,value = テストの値)



スクリーンショット 2019-02-20 1.12.43


まずくっつける列を指定します。
くっつける列は列名でも列番号でもどちらでも構いません。

key = は「1回目、2回目、3回目」に当たる部分の列の名前です。
ここでは回数としました。

value = は実際のデータに当たるところの列の名前です。
ここでは点数としました。


library(tidyverse)
氏名 <- c("A", "B", "C", "D")
年齢 <- c(55, 63, 67, 71)
test_1回目 <- c(1:4)
test_2回目 <- c(5:8)
test_3回目 <- c(9:12)

data <- data_frame(氏名, 年齢, test_1回目, test_2回目, test_3回目)

data %>% 
  gather(3:5, key = 回数, value = 点数) 

スクリーンショット 2019-02-20 1.29.48

変数名の頭を数字にするとRに怒られますので、1回目とせずtest_1回目としています。

それと今回data.frame関数ではなくdata_frame関数を使っています。
どちらも基本的には変わりませんが、data_frame関数はtidyverseパッケージに含まれている関数で、プログラミング初心者であれば少し機能が高いものといった程度で構わないと思います。data.frameとしても大丈夫です。



4.spread関数の使い方

スクリーンショット 2019-02-20 1.26.47

spread関数はlongデータから戻します。

data %>%
gather(3:5, key = 回数, value = 点数) %>% 
  spread(key = 回数, value = 点数)
  スクリーンショット 2019-02-20 1.40.16


gather関数でlongデータにしたものをそのままspread関数でwideデータに戻しました。

そのためもとのdataに戻っています。


5.実際にやってみる

今回はExcelで架空のデータを作りました。

FIM.xlsx

スクリーンショット 2019-02-19 22.25.41


データには氏名・年齢・性別・時期とFIM(18項目の評価と運動項目合計、認知項目合計、全体の合計)が入っています。運動合計は1~13項目目の合計、認知は14~18項目目の合計、FIM合計は18項目の合計です。
そしてタブには「入院時・1ヶ月・退院時」というタブがあります。


ダウンロードした後、プロジェクトの指定フォルダにファイルを移動させておけば、以下のコマンドで上記の画面まで進みます。今回は入院時のデータのみ使います。

liburary(tidyverse)
library(readxl)
fim <- read_excel("FIM.xlsx", sheet = "入院時")
view(fim)


まずどんなデータか確認してみます。

head(fim)
str(fim)
スクリーンショット 2019-02-20 1.54.48

スクリーンショット 2019-02-20 1.55.46

100 obs. of  25 variablesと書いてあるので100人のデータで25列あるということです。

列が多いので、列番号も取得します。
列番号を取得する時はt関数とnames関数の組み合わせが便利です。
またはdata.frame関数とnames関数の組み合わせでもできます。

t(names(fim))
data.frame(names(fim))

スクリーンショット 2019-02-20 2.01.28


この中で5列目の「食事」から25列目の「FIM合計」まではいってしまえば全部FIMというテストの点数です。

なので、これを全部gather関数でまとめてlongデータに変えます。

ここではkeyを回数、valueを点数という列名にしました。好きな名前で構いません。
下の結果を見て、keyとvalueの関係を確認してみてください。

fim_long <- fim %>% 
  gather(食事:FIM合計, key = 項目, value = 点数) 

スクリーンショット 2019-02-20 23.00.29


氏名〜時期までは変わっていませんが、5列目〜25列目がなくなり、代わりに「項目」と「点数」という列ができています。

またA tibble: 2,100 x 6となっており、2100行×6列の表に変わりました。
だいぶ縦長に変わりました。


まとめ

今回はlongデータ、wideデータの説明とgather関数(spread関数も)を紹介しました。

まだこれだけではメリットがわからないと思います。

しかし次に行うgroup_by関数とsummarize関数を行う時やグラフを作る時にこの作業が大きな意味を持つことになります。

次回はこのデータを使って要約(グループごとの平均や標準偏差など)をしていきます。


追記

gather関数のkey = でつなげた要素は五十音順になっている


gather関数でlongデータにした場合、key =に当たる部分の要素はどうなっているのでしょうか?

class(fim_long$項目)
スクリーンショット 2019-02-20 23.30.38


項目は"character"(文字列)となっています。

そしてこのままグラフを作ると下の左の図のように並びが五十音順となります。
これでは困ります。できれば右図のようにもとの順で並べたいところです。

スクリーンショット 2019-02-20 22.22.01



gather関数にfactor_key = TRUEをつける


gather関数内でfactor_key = TRUEを加えるとkeyの列をfactor型にし、順番も元の順番になります。
https://tidyr.tidyverse.org/reference/gather.html より

fim_long <- fim %>% 
  gather(食事:FIM合計, key = 項目, value = 点数, factor_key = TRUE) 
fim_long

class(fim_long$項目)
スクリーンショット 2019-02-21 1.27.33


こうすると集計やグラフ作成で順番が崩れずに表示することができます。