Отслеживание изменений в последовательности в R - PullRequest
3 голосов
/ 31 октября 2019

Я спросил что-то похожее здесь , но функция дала некоторую проблему, я постараюсь сделать это как можно яснее.

У меня есть примерный набор данных, который выглядит следующим образом:

 id <-       c(1,1,1, 2,2,2, 3,3, 4,4, 5,5,5,5, 6,6,6, 7, 8,8)
    item.id <-  c(1,1,2, 1,1,1 ,1,1, 1,2, 1,2,2,2, 1,1,1, 1, 1,2)
    sequence <- c(1,2,1, 1,2,3, 1,2, 1,1, 1,1,2,3, 1,2,3, 1, 1,1)
    score <-    c(0,0,0, 0,0,1, 2,0, 1,1, 1,0,1,1, 0,0,0, 1, 0,2)

    data <- data.frame("id"=id, "item.id"=item.id, "sequence"=sequence, "score"=score)
> data
    id item.id sequence score
1   1       1        1     0
2   1       1        2     0
3   1       2        1     0
4   2       1        1     0
5   2       1        2     0
6   2       1        3     1
7   3       1        1     2
8   3       1        2     0
9   4       1        1     1
10  4       2        1     1
11  5       1        1     1
12  5       2        1     0
13  5       2        2     1
14  5       2        3     1
15  6       1        1     0
16  6       1        2     0
17  6       1        3     0
18  7       1        1     1
19  8       1        1     0
20  8       2        1     2

id представляет для каждого учащегося, item.id представляет вопросы, которые задают ученики, sequence - это номер попытки для каждого item.id, а score - это оценка для каждой попытки,набрав 0,1 или 2. Учащиеся могут изменить свои ответы.

Для item.id в каждом id я хочу создать переменную (status), просматривая последние две последовательности (изменения):

a) assign "WW" for those who changed from wrong to wrong,
b) assign "WR" for those who changed from wrong to right,
c) assign "RW" for those who changed from right to wrong, and
d) assign "RR" for those who changed from right to right.

изменение оценки от 0 до 1 или от 0 до 2 считается правильным (правильным) изменением, в то время как изменение оценки от 1 до 0 или от 2 до 0 считается неправильным (неправильным) изменением.

Если для item.id есть только одна попытка, как в id = 7, тогда status должно быть "one.right". Если score было 0, то оно должно быть "one.wrong". Между тем, score считается right, когда оно равно 1 или 2, score считается неправильным, когда оно равно 0.

желаемый результат будет в случаях:

 > desired
  id item.id    status
  1   1       1        WW
  2   1       2 one.wrong
  3   2       1        WR
  4   3       1        RW
  5   4       1 one.right
  6   4       2 one.right
  7   5       1 one.right
  8   5       2        RR
  9   6       1        WW
  10  7       1 one.right
  11  8       1 one.wrong
  12  8       2 one.right

Есть мнения? Спасибо!

Ответы [ 3 ]

4 голосов
/ 31 октября 2019
library(dplyr)
library(purrr)
library(forcats)

data %>% 
  mutate(status = ifelse(score > 0, "R", "W")) %>% 
  group_by(id, item.id) %>% 
  filter(sequence == n() - 1 | sequence == n()) %>%  
  summarise(status = paste(status, collapse = "")) %>% 
  ungroup() %>% 
  mutate(status = fct_recode(status, "one.wrong" = "W", "one.right" = "R"))

Я полагаю, что это в значительной степени самоописание, но я разобью его:

1) В первом mutate мы создаем столбец W / R из score: 0дает «W», все выше дает «R».

2) Затем мы группируем данные по id, item.id и выбираем последние две строки или просто сохраняем строку, если в группе только одна(filter).

3) После этого мы сжимаем этот столбец status в одну строку в каждой группе (summarize). Таким образом, возможные значения: «W», «R», «WW», «WR», «RW», «RR».

4) Последнее, что остается сделать, это перекодировать »W 'to' one.wrong 'и' R 'to' one.right ', используя forcats::fct_recode.

1 голос
/ 31 октября 2019

Это решение , вдохновленное @laroslavDomin:

library(data.table)
setDT(data)

data[, {
  if (.N == 1) {
    if (score == 0) {
      'one.wrong'
    } else {
      'one.right'
    }
  } else {
    paste0(ifelse(score > 0, 'R', 'W')[c(1, .N)], collapse = '')
  }
},
by = .(id, item.id)]
1 голос
/ 31 октября 2019

Похоже, но не так элегантно, как ответ @laroslav Domin:

library(tidyverse) 
data %>%
  group_by(id, item.id) %>%
  top_n(2, sequence) %>%
  mutate(sequence = row_number()) %>%
  pivot_wider(names_from = sequence, 
              names_prefix = "c", 
              values_from = score) %>%
  mutate(result = case_when(
    c1 == 0 & c2 == 0 ~ "WW",
    c1 == 0 & c2 >  0 ~ "WR",
    c1 >  1 & c2 == 0 ~ "RW",
    c1 >  1 & c2 >  0 ~ "RR",
    c1 == 0 ~ "one.wrong",
    c1 >  0 ~ "one.right",
    TRUE ~ "OTHER")
  )
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...