UPDATE: 2023-06-13 11:28:24
GoogleFormのマルチアンサーを処理する方法をここではまとめておく。
GoogleFormのマルチアンサーをエクスポートすると下記のようなq2
カラムの形式でエクスポートされるらしい。確かに一般的なアンケートツールからエクスポートされる値の形式とは異なる。ちなみにc
という選択肢は存在しているが、だれも回答していケースを想定している。
library(tidyverse)
library(rlang)
<- tibble(
df id = 1:5,
q1 = c(1,2,3,4,2),
q2 = c('a,b,d','a,b','b,d','a,d','d')
) df
## # A tibble: 5 × 3
## id q1 q2
## <int> <dbl> <chr>
## 1 1 1 a,b,d
## 2 2 2 a,b
## 3 3 3 b,d
## 4 4 4 a,d
## 5 5 2 d
すぐに思いつく方法としては、文字列を含んでいたら、TRUE
なり、その選択肢をif_else
関数で返す方法。
%>%
df mutate(
q2_a = if_else(str_detect(q2, 'a'), 'a', NA),
q2_b = if_else(str_detect(q2, 'b'), 'b', NA),
q2_c = if_else(str_detect(q2, 'c'), 'c', NA),
q2_d = if_else(str_detect(q2, 'd'), 'd', NA)
)
## # A tibble: 5 × 7
## id q1 q2 q2_a q2_b q2_c q2_d
## <int> <dbl> <chr> <chr> <chr> <chr> <chr>
## 1 1 1 a,b,d a b <NA> d
## 2 2 2 a,b a b <NA> <NA>
## 3 3 3 b,d <NA> b <NA> d
## 4 4 4 a,d a <NA> <NA> d
## 5 5 2 d <NA> <NA> <NA> d
できなくはないが、これでは選択肢20個あるなら、20行必要になるし、マルチアンサー質問が5つあると、100行必要になる。上記のように機能する関数を書けば良いのでは?という話があるが、下記のよううな方法でもできそうなので、ここではその方法をまとめておく。
まずは選択肢のユニークなベクトルを作成しておく。
<- separate_rows(df, q2, sep = ",") %>%
col_val select(q2) %>%
distinct() %>%
pull() %>%
append('c') %>%
sort()
col_val
## [1] "a" "b" "c" "d"
この選択肢ベクトルを利用して、map2_dfc
関数で、カラム内の値を選択肢ベクトルの値の長さ分、判定してリストを作成する。そして、そのリストをデータフレーム化する。あとは、mutate
関数の部分で、カラム名を使って、値を置換し、再度カラム名を修正する。
%>%
df ::select(q2) %>%
dplyr::map2_dfc(.x = ., .y = col_val, .f = function(x, y) {str_detect(x, pattern = y)}) %>%
purrr::set_names(col_val) %>%
rlang# dplyr::mutate_if(is.logical, function(x){if_else(x, quo_text(quo(x)), NA_character_)})
::mutate(across(is.logical, ~ if_else(.x, quo_text(quo(.x)), NA_character_))) %>%
dplyr::set_names(str_c('q2_', col_val)) %>%
rlang::bind_cols(df, .) dplyr
## # A tibble: 5 × 7
## id q1 q2 q2_a q2_b q2_c q2_d
## <int> <dbl> <chr> <chr> <chr> <chr> <chr>
## 1 1 1 a,b,d a b <NA> d
## 2 2 2 a,b a b <NA> <NA>
## 3 3 3 b,d <NA> b <NA> d
## 4 4 4 a,d a <NA> <NA> d
## 5 5 2 d <NA> <NA> <NA> d
場合にもよるが、アンケートの仕様がそこまで変わらないのであれば、めんどくさいけどif_else
関数の方法のほうが可読性は高いかも。
一晩寝たらそもそもこんなことしなくても下記の方法でも実現できそうなことに気がついたのでメモしておく。
%>%
df ::select(-q1) %>%
dplyr::separate_rows(q2, sep = ',') %>%
tidyr::pivot_wider(
tidyrnames_from = q2,
names_prefix = 'q2_',
values_from = q2,
values_fill = NA_character_
%>%
) mutate(q2_c = NA_character_) %>%
::select(-id) %>%
dplyr::bind_cols(df, .) dplyr
## # A tibble: 5 × 7
## id q1 q2 q2_a q2_b q2_d q2_c
## <int> <dbl> <chr> <chr> <chr> <chr> <chr>
## 1 1 1 a,b,d a b d <NA>
## 2 2 2 a,b a b <NA> <NA>
## 3 3 3 b,d <NA> b d <NA>
## 4 4 4 a,d a <NA> d <NA>
## 5 5 2 d <NA> <NA> d <NA>