Googleスプレッドシートの質問紙(アンケート)処理をR(dplyr)で行う
最近,Googleフォーム&Googleスプレッドシートで質問紙調査を行う機会ができ,Googleスプレッドシートの処理をdplyr + stringiで行ったので,そのメモです。 dplyrはtidyverseパッケージに含まれるので,tidyverseをインストールしておいてください。
質問紙調査でよくあるパターン別にまとめてみます(随時追加していく予定です)。
まず,Googleフォームで質問紙を行った際にどのようにGoogleスプレッドシートに出力されるかを考慮しないといけません。 基本的に,Googleフォームの質問項目への回答はGoogleスプレッドシートに以下のような形で出力されます。
- 参加者1行で,各質問項目が1列で出力される
- 質問項目の1行目は質問項目で,2行目からは参加者の選択肢
- 質問項目は質問文すべてが1セルに出力される(例えば,「問1. 現在の気分を教えて下さい」という質問は,この質問文がそのまま出力される)
- 参加者の回答は選択した選択肢文が出力される(例えば,「5.どちらでもない」を選択すると,この選択肢文がそのまま出力される)
つまり,ほとんどのデータが文字型で出力されるため,分析にあたっては多くのデータは数値型に変換することが必要となります。 また,変数名も質問文になっていて,冗長なので簡便な名前に変更する方がよいです(例えば,尺度名+項目番号でCESD1〜CESD20など)。 さらに,逆転項目処理もざっとやってしまいたいということがあります。
まとめてみると,dplyrをつかって主に以下の作業をしたいわけです。実際はこれに追加でα係数の算出なども行うこともありますね。
- 質問項目文のままの列名を尺度名+項目番号へ変更
- 選択肢を数値に変換
- 逆転項目処理
- 尺度ごとの合計点の算出
なお,実際はパイプ(%>%)で連続でやる方が効率的です。 以下のコードについて間違いや改善点があればご指摘いただけると嬉しいです。
はじめに
データはirisを使います。質問紙のデータではないですが,処理自体はできるでそのままやります。
列名の変更
列名(1列だけ)の変更
renameで簡単にできます。
library(tidyverse) dat <- iris dat <- rename(dat, S = Species) head(dat, 3)
実行結果
Sepal.Length Sepal.Width Petal.Length Petal.Width S 1 5.1 3.5 1.4 0.2 setosa 2 4.9 3.0 1.4 0.2 setosa 3 4.7 3.2 1.3 0.2 setosa
列名(複数列)の変更
複数の列を一括で連番を与えて変更する例です。 ちょっと特殊なやり方かもしれませんが,selectは列を選ぶと同時に列名を変更でき,その時に複数列を持ってくると変更する列名+連番にすることができます。
そこで,変更したい列を取得して列名を連番で変更した上で,さらに残りをeverything()で持ってきます。 コードでは,列番号の1列目から3列目をvar1〜var3に変えています。列番号で指定しているのは,Googleスプレッドシートだと列名(変数名)が質問項目文そのままなので,列名での指定がかなり面倒なためです。 これを尺度ごとに実行することで,尺度名+項目番号に変更できます。
selecetを使っていますが,renameかその派生形を使って,もっとよいやり方はありそうな予感・・・。
library(tidyverse) dat <- iris select(dat, everything(), var = 1:3) head(dat,3)
実行結果
var1 var2 var3 Petal.Width Species 1 5.1 3.5 1.4 0.2 setosa 2 4.9 3.0 1.4 0.2 setosa 3 4.7 3.2 1.3 0.2 setosa
データの変換
文字列を数値に変換
質問紙では,「まったく当てはまらない」〜「非常によく当てはまる」というような選択肢から回答してもらうことが非常に多いです。 Googleフォームでは選択肢をそのまま出力するので,「1. まったく当てはまらない」などといった選択肢にしておけば,最初の1文字目を取得すればOKなのですが,場合によっては数値を当てにくい場合もあります。 そこで入力されているデータに応じて,数値に変換する必要があります。
mutate_atを用いて一括で変換が可能です。mutate_atはvars()に変数名,list(~ )でvarsで指定した変数に対して,list内の処理を行えます。 前はlist(~)ではなく,funs()だったようですが,list(~ )を用いることが推奨されています。
ここでは,case_when()という合致する条件ごと処理を行う関数を実施しています。 例えば, . == "setosa" ~ 1で,当該データがsetosaだったら1に変換という意味です。 ちなみに.(ピリオド)は当該データを表しています。
この例では,varsは1変数だけですが,ここに複数の変数を入れることで一括で変換できます。
library(tidyverse) dat <- iris dat <- mutate_at(dat, vars(Species), list(~case_when( . == "setosa" ~ 1, . == "versicolor" ~ 2, . == "virginica" ~ 3, ))) head(dat,3)
実行結果
Sepal.Length Sepal.Width Petal.Length Petal.Width Species 1 5.1 3.5 1.4 0.2 1 2 4.9 3.0 1.4 0.2 1 3 4.7 3.2 1.3 0.2 1
データの1文字目だけを残す
前述したようにGoogleフォームで,「1. まったく当てはまらない」とした場合には数値の部分だけ(つまり1文字目)だけを残す必要があります。この場合はmutate_at()とstringiパッケージのstr_sub()で複数の変数で1文字目だけを残せます。 str_sub()は指定したデータの何文字目から何文字目までを取ってくる関数です。
この例では,文字列の1文字目を持ってきていますが,「1. まったく当てはまらない」などの場合は,1文字目を持ってきて数値に変換したいので,list(~as.numeric(str_sub(.,1,1)))と書くと良いかもしれません。
なお,上の例と同様にvars()には複数の変数を指定できます。
library(tidyverse) library(stringi) dat <- iris dat <- mutate_at(dat, vars(Species), list(~str_sub(.,1,1))) head(dat,3)
実行結果
Sepal.Length Sepal.Width Petal.Length Petal.Width Species 1 5.1 3.5 1.4 0.2 s 2 4.9 3.0 1.4 0.2 s 3 4.7 3.2 1.3 0.2 s
逆転項目処理
尺度によっては質問項目に逆転項目が含まれます。その場合には逆転項目の逆転処理(数値を逆にする)が必要になります。 よく知られているように「(選択肢の最大値 + 1) - 逆転項目の値」を行うことで逆転項目の処理ができます。
今回は,逆転項目処理を一括で行いつつ,新たに逆転項目処理をした変数(○○_R)を作成するコードにしてみました。新しい項目として作成するのは,当該項目に上書きすると,逆転処理をしたかどうかがわからなくなる可能性を減らすためです。
ここでもmutateとmutate_at()が活躍します。
1項目だけの逆転項目処理
4からSepal.Widthを引いたSepal.Width_Rを作成します。
library(tidyverse) dat <- iris dat <- mutate(dat, Sepal.Width_R = 4-Sepal.Width) head(dat,3)
実行結果
Sepal.Length Sepal.Width Petal.Length Petal.Width Species Sepal.Width_R 1 5.1 3.5 1.4 0.2 setosa 0.5 2 4.9 3.0 1.4 0.2 setosa 1.0 3 4.7 3.2 1.3 0.2 setosa 0.8
1項目だけの逆転項目処理
4からvars()内の変数の値を引いた,各変数_Rを作成します。
library(tidyverse) dat <- iris dat <- mutate_at(dat, vars(Sepal.Width, Sepal.Length), list(R = ~4-.)) head(dat,3)
実行結果
Sepal.Length Sepal.Width Petal.Length Petal.Width Species Sepal.Width_R Sepal.Length_R 1 5.1 3.5 1.4 0.2 setosa 0.5 -1.1 2 4.9 3.0 1.4 0.2 setosa 1.0 -0.9 3 4.7 3.2 1.3 0.2 setosa 0.8 -0.7
合計得点の作成
合計点の算出はmutateで簡単にできます。
library(tidyverse) dat <- iris dat <- mutate(dat, total = Sepal.Width + Sepal.Length) head(dat,3)
実行結果
Sepal.Length Sepal.Width Petal.Length Petal.Width Species total 1 5.1 3.5 1.4 0.2 setosa 8.6 2 4.9 3.0 1.4 0.2 setosa 7.9 3 4.7 3.2 1.3 0.2 setosa 7.9
終わりに
もっと詳しいことを知りたい方は以下の書籍が参考になります。