タグ:R

今まで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型にし、順番ももとの順番になります。


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

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


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

Rで集計やグラフ作成を行う場面は多くあります。

その際、元の表から分析に使いたい列や行だけを抽出したり、「男性だけを取り出す」みたいに様々な条件にあった行だけを抽出することが必要になります

今回はRで指定した列や行だけを取り出すselect関数、slice関数、filter関数を紹介します。
これらはtidyverseパッケージ内にあるdplyrパッケージの機能です。



今回使う架空のデータは前回と同じものを使用します。

年齢、性別、病名が入っています。
下のコードをまとめてスクリプトにコピペして実行してください。
library(tidyverse)
set.seed(1) 年齢 <- floor(rnorm(100,60,20)) 性別 <- sample(c("男性","女性"),100,replace = TRUE) 病名 <- sample(c("脳梗塞", "脳出血", "骨折", "靭帯損傷","心筋梗塞"), 100, replace = TRUE) data <- data.frame(年齢,性別,病名) head(data)

スクリーンショット 2019-02-10 22.48.49



1.指定した列を抽出するselect関数

select(データの変数名, 選択する列)

スクリーンショット 2019-02-13 20.15.20


select関数では縦の列を抽出します。

列名または列番号で選択します(" "をつけなくてOK)。

もしくは使わない列を選ぶこともできます。

そのため以下の3つのコードは全て同じ結果になります。
data_A <- data %>% 
  select(1,2)
head(data_A)

data_A <- data %>% 
  select(年齢,性別)
head(data_A)

data_A <- data %>% 
  select(1,性別)
head(data_A)

data_A <- data %>% select(-3) head(data_A)

列名で指定する場合は""で囲む必要はないですが、大文字や小文字など間違えないことが大切です。

また列番号の場合「何列目かなんてわからない…」ということもよくあります。

列名と列番号の一覧を知りたい時はt関数とnames関数を使うと便利です
t(names(data))
スクリーンショット 2019-02-13 20.28.22



応用編

応用①
もし列名が連番ならを使います。1番目〜5番目なら1:5と書きます。
select(1:5)

応用②
もっと選びたい列があって1番目と5番目〜10番目と13番目を使いたい場合は以下になります。
select(1, 5:10, 13)

応用③

インデックスという考え方で、選ぶ列番号を入れた変数を予め作成する方法があります。

data %>%
index <- c(1, 5:10, 13)
select(index)
スクリーンショット 2019-02-13 23.31.02


先にindexという変数名を作り、そこに指定する列を選びます。

Rを紹介する本やサイトではindexindという変数名で見かけることがありますが、もちろん好きな変数名で構いません。

indexの便利なところはindexを変えるだけで、本体のコードは1つも変わらないところにあります。

スクリーンショット 2019-02-13 21.08.16

このような考え方は色々な場面で使われます。

特に繰り返しの作業で効果を発揮します。



2.指定した行を抽出するslice関数

slice(データの変数名選択する列)

slice関数はselect関数の行バージョンです。

ただ条件で絞るのはslice関数でなく次に紹介するfilter関数になります。

silce関数は10万桁あって処理に時間かかるから、いきなり全部使わず1000行だけ切り取って、プログラムが動くかどうかテストしてみようみたいな場合に使えます。

他にも下のようなExcelをファイルを読み込むことになってしまい、1行目いらない!下の平均の行いらない!など切り取る列が決まってるときに使います。

スクリーンショット 2019-02-13 21.47.00

slice(2:7)はslice(-1,-8)でもOKです。



3.指定した条件を抽出するfilter関数

filter(データの変数名条件1,条件2)

filter関数は条件にあった行を抽出します。

data_B <- data %>% 
  filter(病名 %in% c("骨折", "靭帯損傷"))
head(data_B)
スクリーンショット 2019-02-13 21.45.33


前回の記事でも出ましたが、条件を付ける場合は演算子を使います。

スクリーンショット 2019-02-11 2.04.40
使い方に自身がない場合はRで数値を複数のカテゴリーに分類するifelse関数、case_when関数、cut関数を紹介しますをご参照ください。


複数の条件で絞る場合

filter関数で複数条件の場合は3つ方法があります。

, でつなぐ

filter関数はfilter(データの変数名条件1,条件2)という形式なので、カンマを使ってつなげることができます。

data_B <- data %>% 
  filter(病名 %in% c("骨折", "靭帯損傷") ,
         性別 == "女性" ,
         年齢 < 60)

%>%でつなぎ、filter関数を重ねる

filter関数は複数あって悪いことはないので、素直に%>%でつなげる方法ことも可能です。
メリットとしてはとりあえずわかりやすいのと、考えた順にコードを追加できるところでしょうか。

下のコードで①と同じ結果になります。
スクリーンショット 2019-02-13 21.56.55


&| で条件を付け加える

& や | でつなぐこともできます。演算子の前後に , は入れません。
今までの方法は全て「かつ」という意味でつないでいたので、「または」の意味でつなぎたい時は | でつなぎましょう。

これも①②と同じ結果になります。
スクリーンショット 2019-02-13 23.10.11



まとめ

今回はselect関数、slice関数、filter関数を紹介しました。

これらの関数は集計やグラフを作成するときによく使います。

今後も出てくる予定なのでわからなくなったら復習に使ってください。




前回はmutate関数を使って列の追加や修正を行いました。
そして最後に以下のコメントで終了しました。
mutate関数を使うと「FIMの合計点」とかだけでなく、年齢を「年代ごとに分類する」だったり、ある評価の「カットオフ値以上とそれ以下」に分けた列をExcelを使わずに作成することができます。
【2-2】Rのmutate関数を使って列の追加や修正を行うより)

今回は連続変数を条件に応じて複数のカテゴリーに変換していきます。

Rではいくつか方法があるのですが、今回はifelse関数、case_when関数、cut関数を紹介します。


今回使う架空のデータは年齢、性別、病名が入っています。
下のコードをまとめてスクリプトにコピペして実行してください。
library(tidyverse)
set.seed(1) 年齢 <- floor(rnorm(100,60,20)) 性別 <- sample(c("男性","女性"),100,replace = TRUE) 病名 <- sample(c("脳梗塞", "脳出血", "骨折", "靭帯損傷","心筋梗塞"), 100, replace = TRUE) data <- data.frame(年齢,性別,病名) head(data)
スクリーンショット 2019-02-10 22.48.49



今回は%>%やmutate関数を使って作業します。
これらの使い方に不安がある場合は前回の記事をご参照ください



1.ifelse関数をつかって分類する

条件から2つに分類する場合

ifelse関数は条件からTRUEとFALSEの2つに分けることができます。

ifelse(条件TRUEの場合FALSEの場合)



まず例としてdata_20という変数名に以下のように分類していきます。
・20歳未満を「未成年」、20歳以上を「成人」
・性別の男性を「male」、女性を「female」

data_20 <- data %>% 
  mutate(成人 = ifelse(.$年齢 < 20 , "未成年", "成人")) %>% 
  mutate(性別 = ifelse(.$性別 == "男性", "male", "female"))
head(data_成人)

スクリーンショット 2019-02-11 0.44.03

スクリーンショット 2019-02-11 0.46.48



条件から3つ以上分類する場合

3つ以上分類するはifelse関数のFALSEにifelseを入れ込みます。

ifelse(条件, TRUE, ifelse(条件2, TRUE, ifelse(条件3, TRUE, FALSE)))

このような形を「入れ子」と呼ぶそうです。繰り返せばいくらでも条件を増やすことができます。


今度は「年代」という変数名で20歳ごとに区切ってみます。
20歳未満なら「0〜」、
そうでなければ40歳未満なら「20〜」
そうでなければ60歳未満なら「40〜」・・・

上のイメージをコードにするとこうなります。

data_age <- data %>% 
  mutate(年代 = ifelse(.$年齢 < 20,"0〜", 
                      		ifelse(.$年齢 <40 ,"20〜", 
                        		ifelse(.$年齢 < 60,"40〜",
                        			ifelse(.$年齢 < 80, "60〜",
                        				ifelse(.$年齢 < 100, "80〜", "100〜")))))) %>% 
  mutate(年代 = factor(.$年代, levels = c("0〜", "20〜", "40〜", "60〜", "80〜", "100〜"), ordered = TRUE))
head(data_age)
スクリーンショット 2019-02-12 21.22.24

 mutate(年代 = factor(.$年代, levels = c("0〜", "20〜", "40〜", "60〜", "80〜", "100〜"), ordered = TRUE)の部分はfactorの順番を並べ替えています。

factorは50音順に並ぶので、もしこれをしなかったらグラフなど作る時に「0〜, 100〜, 20〜・・・」と100歳以上の場所がずれてしまいます。それを修正するためにlevels = でfactorの並べ替えをしています。
参照:【1-10】Rでよく使われる型について説明します。


個人的に感じる「ifelse関数+入れ子」のメリットは「他の関数を覚えなくていい」で、デメリットは終わりの))))))))の数が多すぎて間違えやすく、エラーに悩まされることです(笑)



2.case_when関数を使って分類する

3つ以上の分類で入れ子構造対策で慣れるとわかりやすいのがcase_when関数かもしれません。

case_when(条件A ~ 結果A, 条件B ~ 結果B, 条件C ~ 結果C)

今回は0歳以上 かつ 20歳未満といったように「かつ」が入る時は & を使います

年齢が0歳以上   かつ 年齢が20歳未満 を「0〜」
年齢が20歳以上 かつ 年齢が40歳未満 を「20〜」
年齢が40歳以上 かつ 年齢が60歳未満 を「60〜」・・・

上のイメージをコードにするとこうなります。

data_age <- data %>% 
  mutate(年代 = case_when(
    .$年齢 >= 0  & .$年齢 <20 ~ "0〜",
    .$年齢 >= 20 & .$年齢 <40 ~ "20〜",
    .$年齢 >= 40 & .$年齢 <60 ~ "40〜",
    .$年齢 >= 60 & .$年齢 <80 ~ "60〜",
    .$年齢 >= 80 & .$年齢 <100 ~ "80〜",
    .$年齢 >= 100 ~ "100〜")) %>% 
  mutate(年代 = factor(.$年代, levels = c("0〜", "20〜", "40〜", "60〜", "80〜", "100〜"), ordered = TRUE))

head(data_age)
スクリーンショット 2019-02-12 23.58.42


入れ子よりも( )の数が少ないのがありがたいところです。


数値でなくカテゴリーを条件で更に分類する場合

上記の場合は数値でしたが次のような場合はどうでしょう?

最初に行ったdata_20という変数名に以下のように分類していきます。
・成人という変数名で20歳未満を「未成年」、20歳以上を「成人」とする
・性別の男性を「male」、女性を「female」に変更
・疾患分類という変数名で、骨折・靭帯損傷を「運動器疾患」、脳梗塞・脳出血を「脳血管疾患」、心筋梗塞を「心疾患」とする

data_age <- data %>% 
  mutate(年代 = case_when(
    .$年齢 < 20 ~ "未成年",
    .$年齢 <= 20 ~ "成人")) %>% 
  mutate(性別 = case_when(
    .$性別 == "男性" ~ "male",
    .$性別 == "女性" ~ "female")) %>%
  mutate(疾患分類 = case_when(
    .$病名 %in% c("骨折", "靭帯損傷") ~ "運動器疾患",
    .$病名 %in% c("脳梗塞", "脳出血") ~ "脳血管疾患",
    .$病名 %in% "心筋梗塞" ~ "心疾患"))
head(data_age)
スクリーンショット 2019-02-13 0.58.43


ここで新たな ==%in% が出てきました。

スクリーンショット 2019-02-11 2.04.40
A == Bと A %in% Bは似ていますが、Bにあたる部分で==であれば1つしか入りません。
%in%は1つでも複数でも大丈夫です。

上記のコードで言うと .$性別 == "男性" ~ "male" の==は %in%に変えても大丈夫ですし、.$病名 %in% "心筋梗塞" ~ "心疾患" の %in% は == に変えても大丈夫です。

しかし.$病名 %in% c("骨折", "靭帯損傷") ~ "運動器疾患" に関しては ==に変えるとエラーが出ます。

上記図は今回の記事だけでなく条件式を作る時に必要になる考え方です。


case_when関数のメリットは入れ子構造にならないことで、デメリットとしては2つに分類するならifelseの方がコードが短くなります。



3.cut関数を使って分類する


数値を分類するに限って言うとcut関数も使えます。
cut関数はコードはスッキリしますが、少しクセがあり、おまじないが必要です。

cut(目的の列,
      breaks = (下限, カットする数値, 上限),
      right = FALSE,
      include.lowest = TRUE,
      labels =c("カテゴリー毎の名前"))

スクリーンショット 2019-02-13 1.49.04


「10代・20代」などでは0〜19のような分け方をするので、right = FALSEが必要になります。
加えてinclude.lowest = TRUEを加えないと端の値を読み込まず<NA>とデータなしとみなされてしまいます。


これらをふまえると以下のコードになります。

 data_age <- data %>% 
  mutate(年代 = cut(.$年齢, 
                  breaks = c(0, 20, 40, 60, 80, 100, 120),
                  right = FALSE, 
                  include.lowest = TRUE,
                  labels = c("0〜", "20〜", "40〜", "60〜", "80〜", "100〜")))
head(data_age)
スクリーンショット 2019-02-13 1.51.09


cut関数を使えば細かい条件が必要にならない分、right = や include.lowest = を忘れないように注意が必要です。


補足.mutate関数の組み合わせについて

mutate関数を複数回行うにはいくつかの方法があります。

スクリーンショット 2019-02-16 19.31.02
(追記)2019/02/16更新
すみません。mutate関数では②の方法は使えませんでした。
②の方法は次で紹介するfilter関数で使うことができます。


本来は,でつなぐと1つの行で済むのですが、初心者だと、()や,の数がうまくあわなかったりします。プログラミングの上級者からは意見があるかもしれませんが、プログラミング未経験・初心者はまず自分の覚えやすいものから始めていいと思っています。


まとめ

今回は条件によって分類する方法についてifelse関数、case_when関数、cut関数を紹介しました。

それぞれに特徴がありますので、必要に応じて使い分けてください。

また今回は演算子(<, ==, %in%など)の紹介も行いました。

演算子はデータを集計するときに必要になりますのでまた紹介していきたいと思います。

前回の記事から第2章が始まりました。

第1章:Rの基本的な使い方について知る
第2章:データの扱いに慣れる

【2-1】Rのfor関数、apply関数を使ってまとめて標準偏差などの統計量を求める方法


スクリーンショット 2019-02-08 10.33.40

今回は「合計」など新たな列を追加したり、すでにある列を修正するmutate関数について紹介します。

mutate関数は前回の記事でも行ったパイプ演算子(%>%)と一緒に使うことが多いので、パイプ演算子の練習の意味も含めて紹介していきます。


今回は前回の記事のデータを使います。

data01.xlsx 

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

library(readxl)
data01 <- read_excel("data01.xlsx", sheet = "日本語")
data01$性別 <- factor(data01$性別, levels = c("男性","女性"))
data01$歩行 <- as.factor(data01$歩行)
head(data01)

*注意
もしプロジェクトファイルを作成していない場合はgetwd()と打ち込むと作業フォルダが表示されます、作業フォルダにExcelデータを入れると後は同じです。

getwd()


1.mutate関数を使ってBMIの列を作る

library(tidyverse)  #既に実行していたらなくても可
data01_bmi <- mutate(data01, BMI = 体重 / (身長 / 100)^2)
data01_bmi

スクリーンショット 2019-02-08 13.51.51
つまり今回は以下の3つは同じ意味になります。
data01_bmi <- mutate(data01, data01$BMI = data01$体重 / (身長 / 100)^2)
data01_bmi <- mutate(data01, BMI = .$体重 / (.$身長 / 100)^2)
data01_bmi <- mutate(data01, BMI = 体重 / (身長 / 100)^2)


スクリーンショット 2019-02-08 11.14.23

2乗は ^ を使います。
5の2乗は5^2となりますが、5 ^ 2のようにスペースは空けずにくっつけて使います
+ - * / は前後にスペースを入れて使います()
, は,の後にだけスペースを入れます。前に入れません
%>%はくっつけて使い、前後にスペースを入れます


data01 <- mutate(・・・)とdata01自体を修正すると、コードを振り返る時にどこからがBMIを追加する前のdata01で、どこからがBMIを追加した後のdata01かわからなくなるので、今回は新たにdata01_bmiという変数名を作りました。


1つ注意点なのですが、変数名や列の名前にカンマ( , )やドット( . )、ハイフン( - )をつけないようにしましょう。これらは計算式とご認識されて後でめんどくさいことになります。
対策としてはアンダーバー( _ )を使います。



1−2.パイプ演算子とmutate関数をで同じことをする

今度はパイプ演算子を使って同じことをします。

パイプ演算子(%>%)は解析の流れをスムーズにしてくれます。
データ① %>%
    プログラム② %>%
    プログラム③ %>%
    プログラム④
とすると先程のdata01_selectの用な変数を介することもなく、データ①をプログラム②に送り、その結果をプログラム③に送り、その結果をプログラム④に送るといったことが可能になります
【2-1】Rのfor関数、apply関数を使ってまとめて標準偏差などの統計量を求める方法より引用

library(tidyverse)  #既に実行していたらなくても可
data01_bmi <- data01 %>% mutate(BMI = 体重 / (身長 / 100)^2)
data01_bmi

スクリーンショット 2019-02-08 14.02.31
スクリーンショット 2019-02-08 14.10.43


同じ結果になります。

%>%なんでめんどくさいのでは・・・?と思うかもしれませんが、今回はmutate関数1行で終わる課題だからです。何行もかかるプログラムの時に効果を発揮します。

下の2つのケースではapply関数の後「あれ、小数点以下多すぎ!」となったので結果をそのまま%>%でつないでround関数を使おう!といった使い方ができます。

スクリーンショット 2019-02-05 0.57.27

スクリーンショット 2019-02-05 1.13.08

【2-1】Rのfor関数、apply関数を使ってまとめて標準偏差などの統計量を求める方法


2.既にある列を修正する

次は既にある列を修正します。

今回は以前も紹介した型の変更を行います。
このページの最初に使ったコードをパイプ演算子を使うと以下のようになります。

比較してみてください。
library(readxl)
data01 <- read_excel("data01.xlsx", sheet = "日本語")
data01$性別 <- factor(data01$性別, levels = c("男性","女性"))
data01$歩行 <- as.factor(data01$歩行)
head(data01)

library(tidyverse)
library(readxl)
data01 <- read_excel("data01.xlsx", sheet = "日本語")
data01 <- data01 %>% 
  mutate(性別 = factor(.$性別, levels = c("男性","女性"))) %>% 
  mutate(歩行 = as.factor(.$歩行))
head(data01)
スクリーンショット 2019-02-08 15.05.44

今回は型の修正だけなので、data01に上書きしました。

mutate関数の列の追加か修正は名前が既にあるものであれば「修正(上書き)」され、無いものであれば新しく列が追加されます。


まとめ

今回はmutate関数とパイプ演算子の使い方を練習しました。

修正はdata01$性別 <- 〇〇でもいいのですが、パイプ演算子でつなぎたい場合はmutate関数を使うと覚えておくとわかりやすいです。

mutate関数を使うと「FIMの合計点」とかだけでなく、年齢を「年代ごとに分類する」だったり、ある評価の「カットオフ値以上とそれ以下」に分けた列をExcelを使わずに作成することができます。

 次回もmutate関数を使ってそのような新しい列の作成を行っていきます。

前回は今までの総復習を行いました。
【演習】R初心者が統計をかけるための前準備の流れを復習します : 独学で始める統計×データサイエンス



上記の記事を進めると以下のように統計量をまとめて出すことができますが、summary関数では標準偏差が出ません。
スクリーンショット 2019-02-04 21.49.17


今回は標準偏差を出すいろいろな方法を復習も含め紹介します。

繰り返しのfor関数やapply関数、パイプ演算子(%>%)もはじめて出てきますが、使えるようになるとFIMのような項目が多いものでも1度にまとめて解析できるようになり、いよいよExcelではできない体験をすることができるようになります。

まだ今回の内容であればExcelでも可能ですが、1つずつ進めていきましょう。

1.sd関数で1つずつ出す
2.for関数で繰り返す
3.apply関数を使う
4.tableoneパッケージを使う


今回は前回の記事のデータを使います。

data01.xlsx 

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

library(readxl)
data01 <- read_excel("data01.xlsx", sheet = "日本語")
data01$性別 <- factor(data01$性別, levels = c("男性","女性"))
data01$歩行 <- as.factor(data01$歩行)
summary(data01)

*注意
もしプロジェクトファイルを作成していない場合はgetwd()と打ち込むと作業フォルダが表示されます、作業フォルダにExcelデータを入れると後は同じです。

getwd()




1.sd関数で1つずつ出す

標準偏差を出す関数はsd関数です。

sd(ベクトル)
sd(data01[[3]])
sd(data01[[4]])
sd(data01[[5]])
sd(data01[[6]])
sd(data01[[7]])
sd(data01[[8]])
スクリーンショット 2019-02-04 21.53.36


data.frameからベクトルを表示するには$または[[ ]]を使います。
[[ ]]の中の数字は列番号です。
$でもいいのですが、このようなケースでは列番号のほうが手っ取り早いです。

列番号を確認するにはnames関数t関数(もしくはdata.frame関数)を使うと便利です。

t(names(data01))
スクリーンショット 2019-02-04 23.20.52

data.frame(names(data01))
スクリーンショット 2019-02-04 23.22.06


2.for関数で繰り返す

1個ずつ出すのもいいですが、繰り返しになる作業はfor関数で繰り返すことができます。
for(i in 3:8){
  x <- sd(data01[[i]])
  print(x)
  }

for関数は(◯ in △)と{}の2つに別れています。
スクリーンショット 2019-02-04 23.51.05
スクリーンショット 2019-02-04 23.59.46


スクリーンショット 2019-02-05 0.03.59

ただ結果は出るのですが結果の数字しか出ません。


3-1.apply関数を使う

library(tidyverse)
apply(data01, 2, sd)

スクリーンショット 2019-02-05 0.17.43

スクリーンショット 2019-02-05 0.08.54


下にエラーが出ます。これは「氏名と性別で集計できないからNAにしてますよ!」と怒られています。なのでselect関数で集計する列だけ抜き出します。


library(tidyverse) #既に実行していたらなくても可
data01_select <- select(data01, 3:8) data01_select apply(data01_select, 2, sd)
スクリーンショット 2019-02-05 0.32.27

今回はdata01_selectという変数名にselect関数で3〜8列目だけ抜き出しapply関数を使いました。


スクリーンショット 2019-02-05 0.33.14


ただこの方法はdata01_selectのように間に変数を挟む必要があります。
tidyverseパッケージはこれをスッキリさせるパイプ演算子(%>%)というものがあります。


3−2.パイプ演算子を使ったapply関数

パイプ演算子(%>%)は解析の流れをスムーズにしてくれます。

データ① %>%
    プログラム② %>%
    プログラム③ %>%
    プログラム④

とすると先程のdata01_selectの用な変数を介することもなく、データ①をプログラム②に送り、その結果をプログラム③に送り、その結果をプログラム④に送るといったことが可能になります

library(tidyverse) #既に実行していたらなくても可
data01 %>% #data01に対して
  select(3:8) %>% #3列目(年齢)〜8列目(MMSE)までを選択し
  apply(., 2, sd) #それぞれの列で標準偏差を求めて!

スクリーンショット 2019-02-05 0.55.55
スクリーンショット 2019-02-05 0.57.27


もし四捨五入するならround関数を使います。

library(tidyverse)#既に実行していたらなくても可
data01 %>% #data01に対して
  select(3:8) %>% #3列目(年齢)〜8列目(MMSE)までを選択し
  apply(., 2, sd) %>% #それぞれの列で標準偏差を求めて!
  round(.,2) #小数点2位より下を四捨五入する
スクリーンショット 2019-02-05 1.13.08


4.tableoneパッケージを使う

tableoneパッケージを使うのも1つの方法です。

tableoneパッケージについてはこの記事で紹介しています。
Rで医療統計で必要なtable1を作るtableoneパッケージについて紹介します : 独学で始める統計×データサイエンス

library(tableone)
CreateTableOne(data = data01,
               vars = c("年齢", "身長", "体重", "SIAS", "BBS", "MMSE"))
スクリーンショット 2019-02-05 1.20.05


まとめ

今回は標準偏差を出すいろいろな方法を通じてfor関数やapply関数、パイプ演算子の使い方を紹介しました。

今回は標準偏差(sd)でしたが、平均(mean)や中央値(median)など他の統計量も求めることができます。

for関数やtidyverse(dplyrなど)に関してはまとまった記事もありますが、これからもちょくちょく出てくると思います。その都度復習しながら使い方のイメージを付けていただければいいかと思います。








↑このページのトップヘ