Rメモ(tidyverse)
Rメモ(tidyverse)目次
researchmapのバージョンアップによるリンク切れを修正 2020223
【データハンドリング】
【tidyverseで質問紙の回答データを扱う】
【ggplot2】
【tidyverse関連】
janitorパッケージでtidyな度数分布表やクロス表を作成 修正 20180404
データの要約や欠損値の把握を一覧するのに便利なパッケージ:skimr
0
データの要約や欠損値の把握を一覧するのに便利なパッケージ:skimr
データセットにどんな変数が入っているか要約値を確認したい場合,元々Rで使える方法ではsummary( )関数がありました。
しかし,これだけでは物足りないことも多かったので,もっといろいろつけ加わったものがないだろうかと探していた所,skimrパッケージのskim( )関数という便利な方法にたどりついたので,以下覚書です。
詳しい使い方は公式ドキュメントが充実しています。
まずはirisデータで試してみます。
変数の型別に結果が分かれて出てきています。
数値型(numeric)の結果部分では,人数,平均値と標準偏差,パーセンタイル値に加え,簡単なヒストグラムまで出てきて,データの把握に便利です。
変数を指定して出すこともできます。
iris %>%
skim(Petal.Length, Petal.Width)
欠損値を確認するためにbfiデータを使ってみます。
最初のA1~A5のみ表示していますが,それぞれmissingの列に欠損ケースの数が表示されています。
summary(iris)
Sepal.Length Sepal.Width Petal.Length Petal.Width Species Min. :4.300 Min. :2.000 Min. :1.000 Min. :0.100 setosa :50 1st Qu.:5.100 1st Qu.:2.800 1st Qu.:1.600 1st Qu.:0.300 versicolor:50 Median :5.800 Median :3.000 Median :4.350 Median :1.300 virginica :50 Mean :5.843 Mean :3.057 Mean :3.758 Mean :1.199 3rd Qu.:6.400 3rd Qu.:3.300 3rd Qu.:5.100 3rd Qu.:1.800 Max. :7.900 Max. :4.400 Max. :6.900 Max. :2.500
しかし,これだけでは物足りないことも多かったので,もっといろいろつけ加わったものがないだろうかと探していた所,skimrパッケージのskim( )関数という便利な方法にたどりついたので,以下覚書です。
詳しい使い方は公式ドキュメントが充実しています。
まずはirisデータで試してみます。
library(skimr)
skim(iris)
skim(iris)
Skim summary statistics n obs: 150 n variables: 5 Variable type: factor variable missing complete n n_unique top_counts ordered Species 0 150 150 3 set: 50, ver: 50, vir: 50, NA: 0 FALSE Variable type: numeric variable missing complete n mean sd p0 p25 median p75 p100 hist Petal.Length 0 150 150 3.76 1.77 1 1.6 4.35 5.1 6.9 ▇▁▁▂▅▅▃▁ Petal.Width 0 150 150 1.2 0.76 0.1 0.3 1.3 1.8 2.5 ▇▁▁▅▃▃▂▂ Sepal.Length 0 150 150 5.84 0.83 4.3 5.1 5.8 6.4 7.9 ▂▇▅▇▆▅▂▂ Sepal.Width 0 150 150 3.06 0.44 2 2.8 3 3.3 4.4 ▁▂▅▇▃▂▁▁
変数の型別に結果が分かれて出てきています。
数値型(numeric)の結果部分では,人数,平均値と標準偏差,パーセンタイル値に加え,簡単なヒストグラムまで出てきて,データの把握に便利です。
変数を指定して出すこともできます。
iris %>%
skim(Petal.Length, Petal.Width)
Variable type: numeric variable missing complete n mean sd p0 p25 median p75 p100 hist Petal.Length 0 150 150 3.76 1.77 1 1.6 4.35 5.1 6.9 ▇▁▁▂▅▅▃▁ Petal.Width 0 150 150 1.2 0.76 0.1 0.3 1.3 1.8 2.5 ▇▁▁▅▃▃▂▂
欠損値を確認するためにbfiデータを使ってみます。
library(psych)
skim(bfi)
skim(bfi)
Skim summary statistics n obs: 2800 n variables: 28 Variable type: integer variable missing complete n mean sd p0 p25 median p75 p100 hist A1 16 2784 2800 2.41 1.41 1 1 2 3 6 ▇▇▁▃▃▁▂▁ A2 27 2773 2800 4.8 1.17 1 4 5 6 6 ▁▁▁▁▅▁▇▇ A3 26 2774 2800 4.6 1.3 1 4 5 6 6 ▁▂▁▂▅▁▇▆ A4 19 2781 2800 4.7 1.48 1 4 5 6 6 ▁▂▁▁▃▁▅▇ A5 16 2784 2800 4.56 1.26 1 4 5 5 6 ▁▂▁▂▅▁▇▆
最初のA1~A5のみ表示していますが,それぞれmissingの列に欠損ケースの数が表示されています。
0
連続量の変数を分割してカテゴリ変数に区分する(2)
連続量の変数を分割してカテゴリ変数に区分する でやった作業を,tidyverse,特にdplyrの関数を使ってできるようにしてみます。
まずは上記記事と同様のデータセット作成
そして,カテゴリ変数区分にはcase_when()関数を使います。
カテゴリ変数のagecができたら,count()関数で確認します。
まずは上記記事と同様のデータセット作成
library(tidyverse)
set.seed(123)
Age <- floor(runif(50, min = 20, max = 44.9)) #floorは関数は切り捨て,44を出すにはmaxを44.9に
dat <- tibble(age = Age)
set.seed(123)
Age <- floor(runif(50, min = 20, max = 44.9)) #floorは関数は切り捨て,44を出すにはmaxを44.9に
dat <- tibble(age = Age)
そして,カテゴリ変数区分にはcase_when()関数を使います。
カテゴリ変数のagecができたら,count()関数で確認します。
dat <-
dat %>%
mutate(agec =
case_when(
age >= 20 & age < 30 ~ "20-29",
age >= 30 & age < 40 ~ "30-39",
age >= 40 & age < 45 ~ "40-44"
))
dat %>% count(age, agec) %>% print(n = 25)
dat %>%
mutate(agec =
case_when(
age >= 20 & age < 30 ~ "20-29",
age >= 30 & age < 40 ~ "30-39",
age >= 40 & age < 45 ~ "40-44"
))
dat %>% count(age, agec) %>% print(n = 25)
# A tibble: 22 x 3
age agec n
<dbl> <chr> <int>
1 20 20-29 1
2 21 20-29 2
3 22 20-29 1
4 23 20-29 4
5 25 20-29 3
6 26 20-29 2
7 27 20-29 3
8 28 20-29 1
9 29 20-29 1
10 30 30-39 3
11 31 30-39 4
12 33 30-39 3
13 34 30-39 2
14 35 30-39 1
15 36 30-39 2
16 37 30-39 3
17 38 30-39 1
18 39 30-39 2
19 41 40-44 2
20 42 40-44 4
21 43 40-44 4
22 44 40-44 1
0
janitorパッケージでtidyな度数分布表やクロス表を作成
カテゴリ変数の水準ごとの人数,また変数同士のクロス表を算出する場面は多いと思います。そうした際に,tidyverseの影響を受けたtidyverse-orientedなパッケージ,janitorが便利だったので,使い方を整理してみました。
使用するデータは,psychパッケージのbfiデータです。データについて詳しくはこちら参照。
それではさっそくパッケージの読み込みからです。
中の変数確認。
度数を算出するには当該変数にtable()関数を適用するのがよく用いられていると思います。性別のgender変数で確認してみます。
割合を算出するには,さらにprop.table()で囲む
dplyrのcount( )関数でも同じことができます。
%を出したい場合は,mutateでそれぞれの水準のnを合計nで割った式を書き,新しくfreq変数を作成します。でもちょっとコードが長く感じますよね。
そこで,便利なのがjanitorパッケージのtabyl( )関数。これなら%>%でつないで関数に変数名を入れるだけでOK
では,次のような場合はどうでしょう。教育歴を表す変数,educationです。
実は,この変数には欠損値があるので,それを表示させる引数を追加します。
割合はさらに囲む
なんだかごちゃごちゃしてて見にくいですね。
dplyrのcountを使えば,NAはデフォルトで出してくれます。しかも結果もデータフレームで扱いやすいです。
割合を出すには,mutateでnを合計で割った式を書きます
欠損値を無視したい場合はfilterで指定
それではtabyl( )の便利さを見てみましょう
基本的なコードで欠損値を削除した時の値なども出してくれる。
さらに,総計の数が欲しいときはadorn_totals()関数を加えます。
割合を出してみます。多くの場合,興味あるのはrowの%かと思います。
例えば,教育歴が1の人達では女性が○○%,といった具合です。
(20180404 修正)
数字が出てきましたが,これは全体から各セルの割合を見た数字なので,欲しい数値ではありません。そこでtabyl( )関数でクロス表を作成してみます。
bfi %>%
tabyl(education, gender)
rowの%を見たい時は,関数adorn_percentages()を%>%でつなぎます。
引数はデフォルトが"row"なので,書かなくても良いですが,分かりやすくするため入れてあります。
(20180404 追記)
※version 1.0.0から,crosstab()はdeprecatedになりました。
以下はversion 0.3.1以前の話になり古いです。
数字が出てきましたが,これは,全体から各セルの割合を見た数字なので,欲しい数値ではありません。janitorでは,crosstab( )という便利関数があります。
rowの%を見たい時は,オプションにpercent = "row"を追加します。
このように欲しい数値が出てきました。
prop.table()と同じく,全体に対する各セルの割合が欲しい場合は,引数にそう指定します。
NAを除外したい場合は,引数 show_na = FALSE を加えます
さらに,adorn_crosstab( )関数を使うとそのまま表にできる感じの出力もできます
使用するデータは,psychパッケージのbfiデータです。データについて詳しくはこちら参照。
それではさっそくパッケージの読み込みからです。
library(tidyverse)
library(janitor)
library(psych)
library(janitor)
library(psych)
中の変数確認。
names(bfi)
[1] "A1" "A2" "A3" "A4"
[5] "A5" "C1" "C2" "C3"
[9] "C4" "C5" "E1" "E2"
[13] "E3" "E4" "E5" "N1"
[17] "N2" "N3" "N4" "N5"
[21] "O1" "O2" "O3" "O4"
[25] "O5" "gender" "education" "age"
1.度数分布(欠損値がない場合)
度数を算出するには当該変数にtable()関数を適用するのがよく用いられていると思います。性別のgender変数で確認してみます。
table(bfi$gender)
1 2
919 1881
割合を算出するには,さらにprop.table()で囲む
prop.table(table(bfi$gender))
1 2
0.3282143 0.6717857
dplyrのcount( )関数でも同じことができます。
bfi %>% count(gender)
# A tibble: 2 x 2
gender n
<int> <int>
1 1 919
2 2 1881
%を出したい場合は,mutateでそれぞれの水準のnを合計nで割った式を書き,新しくfreq変数を作成します。でもちょっとコードが長く感じますよね。
bfi %>%
count(gender) %>%
mutate(freq = n/sum(n))
count(gender) %>%
mutate(freq = n/sum(n))
# A tibble: 2 x 3
gender n freq
<int> <int> <dbl>
1 1 919 0.3282143
2 2 1881 0.6717857
そこで,便利なのがjanitorパッケージのtabyl( )関数。これなら%>%でつないで関数に変数名を入れるだけでOK
bfi %>% tabyl(gender)
gender n percent
1 1 919 0.3282143
2 2 1881 0.6717857
2.度数分布(欠損値がある場合)
では,次のような場合はどうでしょう。教育歴を表す変数,educationです。
table(bfi$education)
1 2 3 4 5
224 292 1249 394 418
実は,この変数には欠損値があるので,それを表示させる引数を追加します。
table(bfi$education, useNA = "ifany")
1 2 3 4 5 <NA>
224 292 1249 394 418 223
割合はさらに囲む
prop.table(table(bfi$education, useNA = "ifany"))
1 2 3 4 5
0.08000000 0.10428571 0.44607143 0.14071429 0.14928571
<NA>
0.07964286
なんだかごちゃごちゃしてて見にくいですね。
dplyrのcountを使えば,NAはデフォルトで出してくれます。しかも結果もデータフレームで扱いやすいです。
bfi %>% count(education)
# A tibble: 6 x 2
education n
<int> <int>
1 1 224
2 2 292
3 3 1249
4 4 394
5 5 418
6 NA 223
割合を出すには,mutateでnを合計で割った式を書きます
bfi %>%
count(education) %>%
mutate(freq = n/sum(n))
count(education) %>%
mutate(freq = n/sum(n))
education n freq
<int> <int> <dbl>
1 1 224 0.08000000
2 2 292 0.10428571
3 3 1249 0.44607143
4 4 394 0.14071429
5 5 418 0.14928571
6 NA 223 0.07964286
欠損値を無視したい場合はfilterで指定
bfi %>%
filter(!is.na(education)) %>%
count(education) %>%
mutate(freq=n/sum(n))
filter(!is.na(education)) %>%
count(education) %>%
mutate(freq=n/sum(n))
education n freq
<int> <int> <dbl>
1 1 224 0.08692278
2 2 292 0.11331005
3 3 1249 0.48467210
4 4 394 0.15289096
5 5 418 0.16220411
それではtabyl( )の便利さを見てみましょう
bfi %>% tabyl(education)
education n percent valid_percent
1 1 224 0.08000000 0.08692278
2 2 292 0.10428571 0.11331005
3 3 1249 0.44607143 0.48467210
4 4 394 0.14071429 0.15289096
5 5 418 0.14928571 0.16220411
6 NA 223 0.07964286 NA
基本的なコードで欠損値を削除した時の値なども出してくれる。
さらに,総計の数が欲しいときはadorn_totals()関数を加えます。
bfi %>%
tabyl(education) %>%
adorn_totals(which = "row")
tabyl(education) %>%
adorn_totals(which = "row")
education n percent valid_percent
1 1 224 0.08000000 0.08692278
2 2 292 0.10428571 0.11331005
3 3 1249 0.44607143 0.48467210
4 4 394 0.14071429 0.15289096
5 5 418 0.14928571 0.16220411
6 <NA> 223 0.07964286 NA
7 Total 2800 1.00000000 1.00000000
3.クロス表
次はgenderとeducationでクロス表をかいてみます。まずはtable( )で。
table(bfi$education,bfi$gender)
1 2
1 93 131
2 103 189
3 356 893
4 134 260
5 152 266
割合を出してみます。多くの場合,興味あるのはrowの%かと思います。
例えば,教育歴が1の人達では女性が○○%,といった具合です。
prop.table(table(bfi$education,bfi$gender))
1 2
1 0.03608847 0.05083430
2 0.03996896 0.07334109
3 0.13814513 0.34652697
4 0.05199845 0.10089251
5 0.05898331 0.10322080
(20180404 修正)
数字が出てきましたが,これは全体から各セルの割合を見た数字なので,欲しい数値ではありません。そこでtabyl( )関数でクロス表を作成してみます。
bfi %>%
tabyl(education, gender)
education 1 2
1 93 131
2 103 189
3 356 893
4 134 260
5 152 266
rowの%を見たい時は,関数adorn_percentages()を%>%でつなぎます。
引数はデフォルトが"row"なので,書かなくても良いですが,分かりやすくするため入れてあります。
bfi %>%
tabyl(education,gender) %>%
adorn_percentages("row")
tabyl(education,gender) %>%
adorn_percentages("row")
education 1 2 1 0.4151786 0.5848214 2 0.3527397 0.6472603 3 0.2850280 0.7149720 4 0.3401015 0.6598985 5 0.3636364 0.6363636
(20180404 追記)
※version 1.0.0から,crosstab()はdeprecatedになりました。
以下はversion 0.3.1以前の話になり古いです。
数字が出てきましたが,これは,全体から各セルの割合を見た数字なので,欲しい数値ではありません。janitorでは,crosstab( )という便利関数があります。
bfi %>% crosstab(education,gender)
education 1 2
1 1 93 131
2 2 103 189
3 3 356 893
4 4 134 260
5 5 152 266
6 NA 81 142
rowの%を見たい時は,オプションにpercent = "row"を追加します。
bfi %>% crosstab(education,gender, percent = "row")
education 1 2
1 1 0.4151786 0.5848214
2 2 0.3527397 0.6472603
3 3 0.2850280 0.7149720
4 4 0.3401015 0.6598985
5 5 0.3636364 0.6363636
6 NA 0.3632287 0.6367713
このように欲しい数値が出てきました。
prop.table()と同じく,全体に対する各セルの割合が欲しい場合は,引数にそう指定します。
bfi %>% crosstab(education,gender, percent = "all")
education 1 2
1 1 0.03321429 0.04678571
2 2 0.03678571 0.06750000
3 3 0.12714286 0.31892857
4 4 0.04785714 0.09285714
5 5 0.05428571 0.09500000
6 NA 0.02892857 0.05071429
NAを除外したい場合は,引数 show_na = FALSE を加えます
bfi %>% crosstab(education,gender, percent = "all", show_na = FALSE)
education 1 2
1 1 0.03608847 0.05083430
2 2 0.03996896 0.07334109
3 3 0.13814513 0.34652697
4 4 0.05199845 0.10089251
5 5 0.05898331 0.10322080
さらに,adorn_crosstab( )関数を使うとそのまま表にできる感じの出力もできます
bfi %>%
crosstab(education,gender, show_na = FALSE) %>%
adorn_crosstab()
crosstab(education,gender, show_na = FALSE) %>%
adorn_crosstab()
education 1 2
1 1 41.5% (93) 58.5% (131)
2 2 35.3% (103) 64.7% (189)
3 3 28.5% (356) 71.5% (893)
4 4 34.0% (134) 66.0% (260)
5 5 36.4% (152) 63.6% (266)
0
ggplot2で変数だけをloopで変えていきながら同じ設定の図をたくさん描く
たとえば,x軸の変数は固定して,y軸の変数をたくさん変えながら図を描きたい,ということがあります。そんな時は,for loopを使うと可能になります。以下,ggplot2で,irisデータを使って説明します。
それでは,X軸を"Petal.Width" に固定し,残りの"Sepal.Length", "Sepal.Width" , "Petal.Length"をy軸に順番に入れていき散布図を書いてみます。
まずは,個々のグラフを格納していく空のlistを作成し,次に,for loopで変えていきたい変数を列挙したオブジェクト vars を作成します。varsには,個々の変数名をc( )内で文字としてつないでいってもよいですが,今回はnames( )で出てくる順番の数値で指定してみました。
次がfor loopの部分です。
簡単に解説すると,for (i in 1:length(vars))という部分で,それ以下のコード部分のiの所が,1~3まで順次代入されて実行されるという事です。列挙すると,
plots[[i]]
y = vars[i]
labs(title= paste0("(",i,") ", "Petal.Widthと", vars[i], "の散布図"))
のiの所に数値が入っていきます。
ここでggplot( )関数のポイントとなるのがaes_stringです。loopを使わない普通の場合はaesだけですが,loopで変わっていく変数名は文字型なので,普通のaesでは読み込めません。なので,文字型を読み込めるaes_stringを使うということです。したがって,x = "Petal.Width"とこちらも文字になっています。
個別の図が見たい場合は,
のように,[[ ]]の中に,見たいものの並び順の数値を入れるとそれだけ見れます。
すべての散布図を表示させる場合には,リストのオブジェクトをそのまま書きます。
library(tidyverse)
names(iris)
names(iris)
[1] "Sepal.Length" "Sepal.Width" "Petal.Length" "Petal.Width" "Species"
それでは,X軸を"Petal.Width" に固定し,残りの"Sepal.Length", "Sepal.Width" , "Petal.Length"をy軸に順番に入れていき散布図を書いてみます。
まずは,個々のグラフを格納していく空のlistを作成し,次に,for loopで変えていきたい変数を列挙したオブジェクト vars を作成します。varsには,個々の変数名をc( )内で文字としてつないでいってもよいですが,今回はnames( )で出てくる順番の数値で指定してみました。
plots <- list()
vars <- names(iris)[1:3]
vars <- names(iris)[1:3]
次がfor loopの部分です。
for (i in 1:length(vars)) {
plots[[i]] <- ggplot(iris, aes_string(x = "Petal.Width", y = vars[i], color = "Species")) +
geom_point() +
labs(title= paste0("(",i,") ", "Petal.Widthと", vars[i], "の散布図"))
}
plots[[i]] <- ggplot(iris, aes_string(x = "Petal.Width", y = vars[i], color = "Species")) +
geom_point() +
labs(title= paste0("(",i,") ", "Petal.Widthと", vars[i], "の散布図"))
}
簡単に解説すると,for (i in 1:length(vars))という部分で,それ以下のコード部分のiの所が,1~3まで順次代入されて実行されるという事です。列挙すると,
plots[[i]]
y = vars[i]
labs(title= paste0("(",i,") ", "Petal.Widthと", vars[i], "の散布図"))
のiの所に数値が入っていきます。
ここでggplot( )関数のポイントとなるのがaes_stringです。loopを使わない普通の場合はaesだけですが,loopで変わっていく変数名は文字型なので,普通のaesでは読み込めません。なので,文字型を読み込めるaes_stringを使うということです。したがって,x = "Petal.Width"とこちらも文字になっています。
個別の図が見たい場合は,
plots[[2]]
のように,[[ ]]の中に,見たいものの並び順の数値を入れるとそれだけ見れます。
すべての散布図を表示させる場合には,リストのオブジェクトをそのまま書きます。
plots
0
tidyverseで質問紙の回答データを扱う(3):項目の値を逆転して合計得点を作る
データの読み込みなど基本事項は第1回の記事を参照してください。
tidyverseで質問紙の回答データを扱う(1):データの読み込みと変数の選択
逆転項目の存在を確認するため,A1からA5までの変数で相関行列を出してみます。
この結果をみると,A1とそれ以外で向きが逆になっていそうだと見当がつきます。実際に項目を見てみると,
確かに,A1だけ項目の記述が他の反対方向でした。
A1からA5の合計得点を作りたい,というときには,A1の項目の値を逆転させておく必要があります。
値の逆転には,dplyrパッケージのrecode()関数が便利です。
これで,逆転項目A1rができたはずです。クロス表で確認してみます。
この通り,きれいに逆転がされています。なお,dplyrのcount()関数でもよいです
A1とA1rだけを並べて最初の15名位を表示してみると具体例を確認できます
新たな変数をデータセットに追加するには,mutate()関数を使います。
ここでは,A1r~A5の合計得点のAtotalという変数を作成しています。
関係する変数だけにしぼって確認してみます。
念のため,欠損値の扱いがどうなったかも確認しておきましょう。
合計得点がNAとなったもののみに限定してみてみます。
tidyverseで質問紙の回答データを扱う(1):データの読み込みと変数の選択
逆転項目の存在を確認するため,A1からA5までの変数で相関行列を出してみます。
bfi_a %>%
select(A1:A5) %>%
cor(use="complete.obs")
#いずれかの変数に欠損のあるケースは除外A1 A2 A3 A4 A5
A1 1.0000000 -0.3416242 -0.2682817 -0.1483927 -0.1826790
A2 -0.3416242 1.0000000 0.4867503 0.3352432 0.3877875
A3 -0.2682817 0.4867503 1.0000000 0.3621720 0.5051762
A4 -0.1483927 0.3352432 0.3621720 1.0000000 0.3067003
A5 -0.1826790 0.3877875 0.5051762 0.3067003 1.0000000
この結果をみると,A1とそれ以外で向きが逆になっていそうだと見当がつきます。実際に項目を見てみると,
#Agreeableness
#A1:Am indifferent to the feelings of others. (q_146)
#A2:Inquire about others' well-being. (q_1162)
#A3:Know how to comfort others. (q_1206)
#A4:Love children. (q_1364)
#A5:Make people feel at ease. (q_1419)
確かに,A1だけ項目の記述が他の反対方向でした。
A1からA5の合計得点を作りたい,というときには,A1の項目の値を逆転させておく必要があります。
1.項目の値を逆転する
値の逆転には,dplyrパッケージのrecode()関数が便利です。
bfir_a$A1r <-
recode(bfir_a$A1,`1`=6, `2`=5, `3`=4, `4`=3, `5`=2, `6`=1) #`old` = new
これで,逆転項目A1rができたはずです。クロス表で確認してみます。
table(bfi_a$A1, bfi_a$A1r, useNA = "ifany")
1 2 3 4 5 6 <NA>
1 0 0 0 0 0 922 0
2 0 0 0 0 818 0 0
3 0 0 0 402 0 0 0
4 0 0 337 0 0 0 0
5 0 223 0 0 0 0 0
6 82 0 0 0 0 0 0
<NA> 0 0 0 0 0 0 16
この通り,きれいに逆転がされています。なお,dplyrのcount()関数でもよいです
bfi_a %>% count(A1,A1r)
A1 A1r n
<int> <dbl> <int>
1 1 6 922
2 2 5 818
3 3 4 402
4 4 3 337
5 5 2 223
6 6 1 82
7 NA NA 16
A1とA1rだけを並べて最初の15名位を表示してみると具体例を確認できます
bfi_a %>%
select(A1,A1r) %>%
slice(1:15)
A1 A1r
1 2 5
2 2 5
3 5 2
4 4 3
5 2 5
6 6 1
7 2 5
8 4 3
9 4 3
10 2 5
11 4 3
12 2 5
13 5 2
14 5 2
15 4 3
2.合計得点を作る
新たな変数をデータセットに追加するには,mutate()関数を使います。
ここでは,A1r~A5の合計得点のAtotalという変数を作成しています。
bfi_a <- bfi_a %>% mutate(Atotal = A1r + A2 + A3 + A4 + A5)
関係する変数だけにしぼって確認してみます。
bfi_a %>% select(A1r, A2:A5, Atotal)
# A tibble: 2,800 × 6
A1r A2 A3 A4 A5 Atotal
<dbl> <int> <int> <int> <int> <dbl>
1 5 4 3 4 4 20
2 5 4 5 2 5 21
3 2 4 5 4 4 19
4 3 4 6 5 5 23
5 5 3 3 4 5 20
6 1 6 5 6 5 23
7 5 5 5 3 5 23
8 3 3 1 5 1 13
9 3 3 6 3 3 18
10 5 5 6 6 5 27
# ... with 2,790 more rows
念のため,欠損値の扱いがどうなったかも確認しておきましょう。
合計得点がNAとなったもののみに限定してみてみます。
bfi_a %>%
select(A1r,A2:A5, Atotal) %>%
filter(is.na(Atotal))
# A tibble: 91 × 6
A1r A2 A3 A4 A5 Atotal
<dbl> <int> <int> <int> <int> <dbl>
1 5 NA 4 6 4 NA
2 NA 4 5 6 4 NA
3 3 5 4 NA 3 NA
4 6 4 NA 6 6 NA
5 6 5 NA 5 6 NA
6 6 NA 4 6 5 NA
7 6 5 NA 6 5 NA
8 5 NA 5 5 2 NA
9 NA 5 4 3 4 NA
10 5 4 4 6 NA NA
# ... with 81 more rows
このように,A1r~A5に1つでもNAがあったら合計得点もNAとなっています。
変更履歴:
2018/09/22 一行で見にくかったコードを複数行に
0
tidyverseで質問紙の回答データを扱う(2):行の選択
データの読み込みなど基本事項は前回の記事を参照してください。
tidyverseで質問紙の回答データを扱う(1):データの読み込みと変数の選択
たとえば,65歳より上の年齢で教育歴が5の者のみに限定したいといった,条件で行を選択したい場合があります。これには,dplyrのfilter()関数を使います。
bfi_a_sub <- bfi_a %>% filter(age>65 & education==5)
bfi_a_sub
条件で「AまたはB」としたいときは,"|" を使います。
まずは変数A1とA2の欠損値を数えてみて,いずれかが欠損している者を全員選んでみます。まずはdplyrのcount()関数を使ってそれぞれの人数の確認から
ということなので,A1は16名,A2は27名に欠損値があることがわかります。では,どちらかに1つでもある者は何人いるかをみてみます。
全部で43名なので,単純に合計した人数が選ばれました。A1とA2ともに欠損している者はいないようです。
ソートをかけて一応確認してみましょう。ちょっと複雑ですが,上記のコードに,さらにarrange()でソートして,最後の17名だけを表示するということをしてみます。なぜか逆順にしてもNAは最後に並ぶみたいなので,slice()で27行目から43行目までを表示というようにしました。
確かにA1とA2共にNAの者はいないようです。
tidyverseで質問紙の回答データを扱う(1):データの読み込みと変数の選択
1.必要な行(ケース,オブザベーション)だけのデータセットを作る
たとえば,65歳より上の年齢で教育歴が5の者のみに限定したいといった,条件で行を選択したい場合があります。これには,dplyrのfilter()関数を使います。
bfi_a_sub <- bfi_a %>% filter(age>65 & education==5)
bfi_a_sub
# A tibble: 5 × 8
A1 A2 A3 A4 A5 gender education age
<int> <int> <int> <int> <int> <int> <int> <int>
1 1 5 6 5 6 1 5 68
2 4 3 1 1 5 1 5 74
3 2 4 4 3 4 1 5 67
4 2 4 4 4 4 1 5 67
5 2 6 6 6 5 2 5 66
条件で「AまたはB」としたいときは,"|" を使います。
まずは変数A1とA2の欠損値を数えてみて,いずれかが欠損している者を全員選んでみます。まずはdplyrのcount()関数を使ってそれぞれの人数の確認から
bfi_a %>% count(A1)
# A tibble: 7 × 2
A1 n
<int> <int>
1 1 922
2 2 818
3 3 402
4 4 337
5 5 223
6 6 82
7 NA 16
bfi_a %>% count(A2)
# A tibble: 7 × 2
A2 n
<int> <int>
1 1 47
2 2 126
3 3 151
4 4 553
5 5 1023
6 6 873
7 NA 27
ということなので,A1は16名,A2は27名に欠損値があることがわかります。では,どちらかに1つでもある者は何人いるかをみてみます。
bfi_a %>% filter(is.na(A1) | is.na(A2))
# A tibble: 43 × 8
A1 A2 A3 A4 A5 gender education age
<int> <int> <int> <int> <int> <int> <int> <int>
1 2 NA 4 6 4 2 3 19
2 NA 4 5 6 4 2 4 36
3 1 NA 4 6 5 2 5 32
4 2 NA 5 5 2 2 5 28
5 NA 5 4 3 4 1 2 49
6 5 NA 5 6 5 2 3 26
7 5 NA 5 6 5 2 3 26
8 NA 6 6 6 6 2 1 39
9 NA 6 6 NA 6 2 3 35
10 2 NA 5 3 6 1 3 20
# ... with 33 more rows
全部で43名なので,単純に合計した人数が選ばれました。A1とA2ともに欠損している者はいないようです。
ソートをかけて一応確認してみましょう。ちょっと複雑ですが,上記のコードに,さらにarrange()でソートして,最後の17名だけを表示するということをしてみます。なぜか逆順にしてもNAは最後に並ぶみたいなので,slice()で27行目から43行目までを表示というようにしました。
bfi_a %>% filter(is.na(A1) | is.na(A2)) %>%
arrange(A1) %>%
slice(27:43)
arrange(A1) %>%
slice(27:43)
# A tibble: 17 × 8
A1 A2 A3 A4 A5 gender education age
<int> <int> <int> <int> <int> <int> <int> <int>
1 6 NA NA NA 4 1 NA 17
2 NA 4 5 6 4 2 4 36
3 NA 5 4 3 4 1 2 49
4 NA 6 6 6 6 2 1 39
5 NA 6 6 NA 6 2 3 35
6 NA 6 3 5 4 2 3 30
7 NA 3 4 3 3 2 NA 17
8 NA 5 4 6 4 2 3 20
9 NA 6 5 4 6 2 3 31
10 NA 6 5 6 6 2 4 50
11 NA 5 6 6 5 2 4 28
12 NA 5 NA 6 6 2 5 22
13 NA 5 6 5 6 2 5 48
14 NA 6 5 6 6 2 3 27
15 NA 6 6 6 NA 2 2 39
16 NA 2 2 5 2 2 3 28
17 NA 6 4 NA 4 2 NA 11
確かにA1とA2共にNAの者はいないようです。
0
tidyverseで質問紙の回答データを扱う(1):データの読み込みと変数の選択
Hadley Wickham氏の作成した様々なパッケージと,それらを一括で読み込むtidyverseパッケージによって,Rにおけるデータハンドリングの作業が劇的にやりやすくなったと思います。その便利さを紹介していく予定です。
調査系の研究をする人になじみやすいように,パッケージpsychのbfiデータを使ってやってみます。bfiデータの説明は以前の記事参照
library(psych)
library(tidyverse)
まずは変数名の一覧を確認
データの最初の6行分を確認
デフォルトのデータフレーム形式だと,このように変数全体を表示するのに複数行も必要になったり不便です。そこで,画面に収まる分だけ出力し,入らない分は情報を省略してくれ,データの型の情報まで示してくれるtibble形式に変換すると,とても便利です。
このように,head()を使わなくて,データセット名直打ちであっても,最初の10行だけ表示され,残りが2,790行であることが分かり,変数も画面に入りきらない分は変数名と型の情報のみ列挙されていて,データセットの情報が非常に把握しやすくなりました。
tidyverseがロードされていれば意識する必要はないですが,helpで詳細を見たい場合もあるので,担当するパッケージ名を示しておきます。使用しているのはdplyrパッケージです。
まず,変数の選択を紹介します。select()の中に残したいデータセット名および変数名を入れるだけです。
これは,以下のように書くこともできます。こうすると,()内が変数名だけになり,すっきりします。
この%>%という記号はパイプ演算子,といいます。簡単に機能を説明すると,%>%の左側にあるものを右側の()の最初の所に入れてくれるような働きをします。これは非常に便利なので,今後これを多用します。
それでは,変数のA1~A5,gender,education, ageだけを残したデータセットbfi_aを作成してみます。
不要な変数のみ取り去りたい場合は,変数名の前に-(マイナス)をつけます。
調査系の研究をする人になじみやすいように,パッケージpsychのbfiデータを使ってやってみます。bfiデータの説明は以前の記事参照
library(psych)
library(tidyverse)
まずは変数名の一覧を確認
names(bfi)
[1] "A1" "A2" "A3" "A4" "A5" "C1" "C2"
[8] "C3" "C4" "C5" "E1" "E2" "E3" "E4"
[15] "E5" "N1" "N2" "N3" "N4" "N5" "O1"
[22] "O2" "O3" "O4" "O5" "gender" "education" "age"
データの最初の6行分を確認
head(bfi)
A1 A2 A3 A4 A5 C1 C2 C3 C4 C5 E1 E2 E3 E4 E5 N1 N2 N3 N4 N5 O1 O2 O3 O4 O5 gender
61617 2 4 3 4 4 2 3 3 4 4 3 3 3 4 4 3 4 2 2 3 3 6 3 4 3 1
61618 2 4 5 2 5 5 4 4 3 4 1 1 6 4 3 3 3 3 5 5 4 2 4 3 3 2
61620 5 4 5 4 4 4 5 4 2 5 2 4 4 4 5 4 5 4 2 3 4 2 5 5 2 2
61621 4 4 6 5 5 4 4 3 5 5 5 3 4 4 4 2 5 2 4 1 3 3 4 3 5 2
61622 2 3 3 4 5 4 4 5 3 2 2 2 5 4 5 2 3 4 4 3 3 3 4 3 3 1
61623 6 6 5 6 5 6 6 6 1 3 2 1 6 5 6 3 5 2 2 3 4 3 5 6 1 2
education age
61617 NA 16
61618 NA 18
61620 NA 17
61621 NA 17
61622 NA 17
61623 3 21
デフォルトのデータフレーム形式だと,このように変数全体を表示するのに複数行も必要になったり不便です。そこで,画面に収まる分だけ出力し,入らない分は情報を省略してくれ,データの型の情報まで示してくれるtibble形式に変換すると,とても便利です。
bfi <- as_tibble(bfi)
bfi
bfi
# A tibble: 2,800 × 28
A1 A2 A3 A4 A5 C1 C2 C3 C4 C5 E1 E2 E3
* <int> <int> <int> <int> <int> <int> <int> <int> <int> <int> <int> <int> <int>
1 2 4 3 4 4 2 3 3 4 4 3 3 3
2 2 4 5 2 5 5 4 4 3 4 1 1 6
3 5 4 5 4 4 4 5 4 2 5 2 4 4
4 4 4 6 5 5 4 4 3 5 5 5 3 4
5 2 3 3 4 5 4 4 5 3 2 2 2 5
6 6 6 5 6 5 6 6 6 1 3 2 1 6
7 2 5 5 3 5 5 4 4 2 3 4 3 4
8 4 3 1 5 1 3 2 4 2 4 3 6 4
9 4 3 6 3 3 6 6 3 4 5 5 3 NA
10 2 5 6 6 5 6 5 6 2 1 2 2 4
# ... with 2,790 more rows, and 15 more variables: E4 <int>, E5 <int>, N1 <int>,
# N2 <int>, N3 <int>, N4 <int>, N5 <int>, O1 <int>, O2 <int>, O3 <int>, O4 <int>,
# O5 <int>, gender <int>, education <int>, age <int>
このように,head()を使わなくて,データセット名直打ちであっても,最初の10行だけ表示され,残りが2,790行であることが分かり,変数も画面に入りきらない分は変数名と型の情報のみ列挙されていて,データセットの情報が非常に把握しやすくなりました。
1.必要な変数だけのデータセットを作る
tidyverseがロードされていれば意識する必要はないですが,helpで詳細を見たい場合もあるので,担当するパッケージ名を示しておきます。使用しているのはdplyrパッケージです。
まず,変数の選択を紹介します。select()の中に残したいデータセット名および変数名を入れるだけです。
select(bfi, gender)
# A tibble: 2,800 × 1
gender
* <int>
1 1
2 2
3 2
4 2
5 1
6 2
7 1
8 1
9 1
10 2
# ... with 2,790 more rows
これは,以下のように書くこともできます。こうすると,()内が変数名だけになり,すっきりします。
bfi %>% select(gender)
この%>%という記号はパイプ演算子,といいます。簡単に機能を説明すると,%>%の左側にあるものを右側の()の最初の所に入れてくれるような働きをします。これは非常に便利なので,今後これを多用します。
それでは,変数のA1~A5,gender,education, ageだけを残したデータセットbfi_aを作成してみます。
bfi_a <-
bfi %>%
select(A1:A5, gender, education, age)
bfi_a
bfi_a
# A tibble: 2,800 × 8
A1 A2 A3 A4 A5 gender education age
* <int> <int> <int> <int> <int> <int> <int> <int>
1 2 4 3 4 4 1 NA 16
2 2 4 5 2 5 2 NA 18
3 5 4 5 4 4 2 NA 17
4 4 4 6 5 5 2 NA 17
5 2 3 3 4 5 1 NA 17
6 6 6 5 6 5 2 3 21
7 2 5 5 3 5 1 NA 18
8 4 3 1 5 1 1 2 19
9 4 3 6 3 3 1 1 19
10 2 5 6 6 5 2 NA 17
# ... with 2,790 more rows
不要な変数のみ取り去りたい場合は,変数名の前に-(マイナス)をつけます。
bfi_a %>% select(-education, -age)
# A tibble: 2,800 × 6
A1 A2 A3 A4 A5 gender
* <int> <int> <int> <int> <int> <int>
1 2 4 3 4 4 1
2 2 4 5 2 5 2
3 5 4 5 4 4 2
4 4 4 6 5 5 2
5 2 3 3 4 5 1
6 6 6 5 6 5 2
7 2 5 5 3 5 1
8 4 3 1 5 1 1
9 4 3 6 3 3 1
10 2 5 6 6 5 2
# ... with 2,790 more rows
変更履歴
2018/09/22 tbl_df → as_tibbleに
0