R: разделение строк «попарно» на переменное количество элементов

#r #tidyverse

#r #tidyverse

Вопрос:

Моя цель — составить структуру вопросника. Для каждого респондента у меня есть значение, дающее ответ на вопрос плюс время ответа: q1:2,q2:3,q4:4,q10:4 означает, что соответствующий респондент q1 сначала ответил на вопрос (через 2 секунды), затем он ответил q2 (через 3 секунды) и так далее до вопроса q10 . Иногда названия вопросов также начинаются с «d» (например d10 ), что является просто другим типом вопросов.

Пример:

 dat <- data.frame(path = c(
  "q1:9,q2:8,d3:10,q10:3,q4:10",
  "q1:10,q2:10,q10:2,q4:2",
  "q1:2,q2:3,d11:2"
))
  

Моя идея состоит в том, чтобы отобразить структуру ответа на вопросник в виде сетевого графика. Поэтому мне нужен длинный список всех различных «шагов», которые респонденты сделали в анкете:

 from | to
------------
q1     q2 # first respondent
q2     d3
d3     q10
q10    q4
q1     q2 # second respondent
q2     q10
q10    q4
q1     q2 # third respondent
q2     d11
...
  

Моя проблема в том, что из-за вопросов с фильтром не всем респондентам приходилось отвечать на одинаковое количество вопросов (поэтому я не могу использовать separate(, into=?) , потому что? является переменным). Кроме того, переменные необходимо разделить «попарно».

У кого-нибудь есть идея, как получить приведенный выше фрейм данных??

Конечной целью, конечно, было бы иметь таблицу, содержащую количество респондентов для каждого «шага» (например, 20 респондентов перешли от q1 к q2 , поэтому 20 можно использовать в качестве весовой переменной на графике).

Спасибо!

Ответ №1:

Вы имеете в виду что-то вроде приведенного ниже?

 do.call(
  rbind,
  lapply(
    strsplit(dat$path, ":\d ,?"),
    function(v) data.frame(from = v[-length(v)], to = v[-1])
  )
)
  

что дает

   from  to
1   q1  q2
2   q2  d3
3   d3 q10
4  q10  q4
5   q1  q2
6   q2 q10
7  q10  q4
8   q1  q2
9   q2 d11
  

Ответ №2:

Опция с str_extract

 library(dplyr)
library(tidyr)
library(stringr)
library(purrr)
dat %>% 
    transmute(from = str_extract_all(path, "\w (?=:)"), to = map(from, lead)) %>%
    unnest(c(from, to)) %>%
    filter(!is.na(to))
  

-вывод

 # A tibble: 9 x 2
#  from  to   
#  <chr> <chr>
#1 q1    q2   
#2 q2    d3   
#3 d3    q10  
#4 q10   q4   
#5 q1    q2   
#6 q2    q10  
#7 q10   q4   
#8 q1    q2   
#9 q2    d11  
  

Ответ №3:

Отвечает ли это:

 > dat %>% mutate(ID = row_number()) %>%  
            separate_rows(path,sep = ',') %>% 
                    extract(col = path, into = c('ques','number'), regex = '(.*):(.*)') %>% 
                                    select(-number) %>% group_by(ID) %>% mutate(from = ques, to = lead(ques)) %>% ungroup() %>% select(c(-ques,-ID)) %>% na.omit()
# A tibble: 9 x 2
  from  to   
  <chr> <chr>
1 q1    q2   
2 q2    d3   
3 d3    q10  
4 q10   q4   
5 q1    q2   
6 q2    q10  
7 q10   q4   
8 q1    q2   
9 q2    d11  
>