перекодировать по правилу расщепления - PullRequest
0 голосов
/ 26 марта 2020

У меня есть набор данных ученика, включая информацию о ученике, question id (5 вопросов), sequence каждого испытания, чтобы ответить на вопросы. Я хотел бы создать переменную для guish, в которой именно ученик начинает просматривать вопросы после завершения всех вопросов.

Вот примерный набор данных:

data <- data.frame(
person =   c(1,1,1,1,1,1,1,1,1,1,1, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2),
question = c(1,2,2,3,3,3,4,3,5,1,2, 1,1,1,2,3,4,4,4,5,5,4,3,4,4,5,4,5),
sequence = c(1,1,2,1,2,3,1,4,1,2,3, 1,2,3,1,1,1,2,3,1,2,4,2,5,6,3,7,4))

data
   person question sequence
1       1        1        1
2       1        2        1
3       1        2        2
4       1        3        1
5       1        3        2
6       1        3        3
7       1        4        1
8       1        3        4
9       1        5        1
10      1        1        2
11      1        2        3
12      2        1        1
13      2        1        2
14      2        1        3
15      2        2        1
16      2        3        1
17      2        4        1
18      2        4        2
19      2        4        3
20      2        5        1
21      2        5        2
22      2        4        4
23      2        3        2
24      2        4        5
25      2        4        6
26      2        5        3
27      2        4        7
28      2        5        4

sequence Переменные записывают каждое посещение, давая порядковый номер. Как правило, можно было бы вернуться, прежде чем увидеть все вопросы. Однако переменная attempt должна записываться только после того, как учащийся увидит все 5 вопросов. С новой переменной я нацеливаюсь на этот набор данных.

> data
   person question sequence attempt
1       1        1        1 initial
2       1        2        1 initial
3       1        2        2 initial
4       1        3        1 initial
5       1        3        2 initial
6       1        3        3 initial
7       1        4        1 initial
8       1        3        4 initial
9       1        5        1 initial
10      1        1        2  review
11      1        2        3  review
12      2        1        1 initial
13      2        1        2 initial
14      2        1        3 initial
15      2        2        1 initial
16      2        3        1 initial
17      2        4        1 initial
18      2        4        2 initial
19      2        4        3 initial
20      2        5        1 initial
21      2        5        2 initial
22      2        4        4  review
23      2        3        2  review
24      2        4        5  review
25      2        4        6  review
26      2        5        3  review
27      2        4        7  review
28      2        5        4  review

Есть идеи? Спасибо!

Ответы [ 2 ]

1 голос
/ 26 марта 2020

Какой сложный вопрос. Потребовалось почти 2 часа, чтобы найти решение.

Попробуйте это

library(dplyr)

dist_cum <- function(var)
  sapply(seq_along(var), function(x) length(unique(head(var, x))))

data %>% 
  mutate(var0 = n_distinct(question)) %>%
  group_by(person) %>% 
  mutate(var1 = dist_cum(question),
         var2 = cumsum(c(1, diff(question) != 0))) %>%
  ungroup() %>%
  mutate(var3 = if_else(sequence == 1 | var1 < var0, 0, 1)) %>%
  group_by(person, var2) %>%
  mutate(var4 = min(var3)) %>%
  ungroup() %>%
  mutate(attemp = if_else(var4 == 0, "initial", "review")) %>%
  select(-starts_with("var")) %>%
  as.data.frame

Результат

   person question sequence  attemp
1       1        1        1 initial
2       1        2        1 initial
3       1        2        2 initial
4       1        3        1 initial
5       1        3        2 initial
6       1        3        3 initial
7       1        4        1 initial
8       1        3        4 initial
9       1        5        1 initial
10      1        1        2  review
11      1        2        3  review
12      2        1        1 initial
13      2        1        2 initial
14      2        1        3 initial
15      2        2        1 initial
16      2        3        1 initial
17      2        4        1 initial
18      2        4        2 initial
19      2        4        3 initial
20      2        5        1 initial
21      2        5        2 initial
22      2        4        4  review
23      2        3        2  review
24      2        4        5  review
25      2        4        6  review
26      2        5        3  review
27      2        4        7  review
28      2        5        4  review

dist_cum - это функция для вычисления отличительного значения прокатки ( Источник ). var0 ... var4 являются помощниками

1 голос
/ 26 марта 2020

Один из способов сделать это - найти место, где начинается рецензирование (т. Е. Следующая запись после того, как был замечен пятый вопрос) и где последовательность равна 2. См. v1 и v2. Затем с помощью поднабора для каждого отдельного человека и зацикливания для каждого поднабора вы можете обновить отсутствующие записи для переменной attempt, поскольку теперь известно, с чего начинается рецензирование.

v1 <- c(FALSE, (data$question == 5)[-(nrow(data))])
v2 <- data$sequence == 2
data$attempt <- ifelse(v1 * v2 == 1, "review", NA)
persons <- unique(data$person)

persons.list <- vector(mode = "list", length = length(persons))

for(i in 1:length(persons)){      
  person.i <- subset(data, person == persons[i])
  n <- which(person.i$attempt == "review")
  m <- nrow(person.i)
  person.i$attempt[(n+1):m] <- "review" 
  person.i$attempt[which(is.na(person.i$attempt))] <- "initial"

  persons.list[[i]] <- person.i
}

do.call(rbind, persons.list)
   person question sequence attempt
1       1        1        1 initial
2       1        2        1 initial
3       1        2        2 initial
4       1        3        1 initial
5       1        3        2 initial
6       1        3        3 initial
7       1        4        1 initial
8       1        3        4 initial
9       1        5        1 initial
10      1        1        2  review
11      1        2        3  review
12      2        1        1 initial
13      2        1        2 initial
14      2        1        3 initial
15      2        2        1 initial
16      2        3        1 initial
17      2        4        1 initial
18      2        4        2 initial
19      2        4        3 initial
20      2        5        1 initial
21      2        5        2  review
22      2        4        4  review
23      2        3        2  review
24      2        4        5  review
25      2        4        6  review
26      2        5        3  review
27      2        4        7  review
28      2        5        4  review

В качестве альтернативы вы можете также используйте lapply:

do.call(rbind, 
        lapply(persons, function(x){
          person.x <- subset(data, person == x)
          n <- which(person.x$attempt == "review")
          m <- nrow(person.x)
          person.x$attempt[(n+1):m] <- "review" 
          person.x$attempt[which(is.na(person.x$attempt))] <- "initial"
          person.x
        }))
...