Прикладная задача
Я хочу абстрагироваться от кода, который обобщает схемы прохождения курса и показатели успешности группы студентов для n курсов и n терминов.
Пример
Со следующей группой студентов, сколько человек пойдет на курс "B" после прохождения курса "A", и сколько из этих студентов преуспели:
data <- data.frame(student = c(1, 1, 1, 2, 2, 2, 3, 4, 4, 5, 5, 5),
term = c(2, 3, 3, 1, 2, 3, 2, 1, 3, 1, 2, 4),
course = c('A', 'B', 'C', 'A', 'B', 'C', 'A', 'B', 'C', 'A', 'A', 'C'),
success = c(1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1),
stringsAsFactors = FALSE)
Мы можем ответить на этот вопрос следующим кодом:
library(dplyr)
# Get each student's first, second, third, ... term.
data <- data %>%
group_by(student) %>%
mutate(term_dense = dense_rank(term))%>%
ungroup()
# Identify those who took course A
courseA <- data %>%
filter(course == "A")%>%
select(student, courseA_dense = term_dense)
# Get records of students who took course A, and their subsequent courses
data <- data %>%
left_join(courseA, by = "student")%>%
filter(term_dense >= courseA_dense) # >= for courses they took in same term as course "A"
# Summarise for each term_dense
data %>%
group_by(term_dense) %>%
summarise(attempted_course_A = sum(course == "A"),
completed_course_A = sum(course == "A" & success == 1),
attempted_course_B = sum(course == "B"),
completed_course_B = sum(course == "B" & success == 1))
, который выдает:
# A tibble: 3 x 5
term_dense attempted_course_A completed_course_A attempted_course_B completed_course_B
<int> <int> <int> <int> <int>
1 1 4 2 0 0
2 2 2 2 2 2
3 3 0 0 0 0
, и мы можем видеть, что из студентов, которые пытались пройти курсА, это 2 попытки курса Б, оба из которых были успешными.
Теперь я могу вычислить, сколько человек взяло курс "С" после , пройдя курс "А", добавив строки в summarise
утверждение (то есть completed_course_C = sum(course == "C" & success == 1)
), но если у меня много курсов, это не кажется наиболее эффективным вариантом.
Кроме того, если я хочу обобщить последовательность курса "X" после курса «Y» для любых «X» и «Y» создается еще больше перестановокиз summarise
заявлений.И как мне смотреть на тех, кто взял «X» после «Y» после «Z».
Итак, как мне суммировать прогресс курсаи показатели успешности для различного количества курсов по разному количеству терминов?
Желаемый результат
Я думаю, что именно в этом и заключаются некоторые из моих трудностей.Я не знаю, как должно получиться структурированное data.frame
.
Я знаю, что хотел бы легко ответить на следующий общий вопрос, однако:
"X% студентов, которые были успешными в курсе" A ", впоследствии прошли курс" B "ипоказатель успешности Y% "
Абстрактная проблема
Я пытался применить общую проблему (отслеживание / последовательность когорт?) к другим полям, чтобы получить лучшие ключевые слова /Результаты поиска в Google и Stack Overflow.Тот, который казался многообещающим, использует сетевой анализ.
В частности, этот пост, Сетевой анализ с R , был полезен при определении потенциального решения.Я следовал этой статье, используя вместо этого мои данные, и смог получить около половины моей информации.Используя этот метод, я смог получить только последовательность попыток или последовательность успешных попыток - но не обе.Но я только начал изучать сетевой анализ.
На самом деле, я смог вручную визуализировать сводку, используя диаграмму Санки plotly
, которая использует аналогичную сеть /рамки ссылок.Но я до сих пор не смог программно рассчитать эту информацию.
Другие попытки
Учитывая, что я хочу по существу «сопоставить» сводную функцию с моими данными, многие из моих попыток использовалипакет purrr
с вложенными списками-столбцами.
purrr
попыток
Используя оригинальный data
сверху, я попытался вложить список курсов студентов в соответствии с их ранжированными терминами.
# library(dplyr) # Loaded in above example
library(tidyr)
library(purrr)
data <- data %>%
group_by(student) %>%
mutate(term_dense = dense_rank(term)) %>%
ungroup()%>%
nest(term, course, success, .key = "schedule")
Затем я попытался создать функцию, которая возвращала бы сводку исходного курса к целевому курсу с конечной целью map
этой функции в список, содержащий все уникальныеперестановки источника и цели:
attempt_summary <- function(df, source, target){
temp_df <- df %>%
filter(map_lgl(schedule, ~any(.x$course == source)))%>%
select(student, source_term_dense = term_dense)
df <- df %>%
left_join(temp_df, by = "student")%>%
filter(term_dense >= source_term_dense)
df %>%
group_by(term_dense) %>%
summarise(completed_source = sum(map_int(schedule, ~any(.x$course == source & .x$success == 1))),
attempted_target = sum(map_int(schedule, ~any(.x$course == target))),
completed_target = sum(map_int(schedule, ~any(.x$course == target & .x$success == 1))))
}
Функция работает для одного примера,
attempt_summary(data, "A", "B")
# A tibble: 3 x 4
term_dense completed_source attempted_target completed_target
<int> <int> <int> <int>
1 1 2 0 0
2 2 2 2 2
3 3 0 0 0
, но я не мог понять, как сопоставить ее со всем остальным (я не могдаже понять, как структурировать мои списки целей и источников), но здесь была моя попытка:
# DO NOT RUN - DOESN'T WORK
# map(data, attempt_summary, source = src_list, target = trgt_list)
Сообщения переполнения стека
В дополнение ко многим другим о purrr
, я ссылался на эти сообщенияв поиске решения, но ничего из того, что я искал, не было.
Информация о сеансе
Вот результат моего sessionInfo()
звонка:
> sessionInfo()
R version 3.5.3 (2019-03-11)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 10 x64 (build 17763)
Matrix products: default
locale:
[1] LC_COLLATE=English_United States.1252 LC_CTYPE=English_United States.1252
[3] LC_MONETARY=English_United States.1252 LC_NUMERIC=C
[5] LC_TIME=English_United States.1252
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] purrr_0.3.2 tidyr_0.8.3 dplyr_0.8.0.1
loaded via a namespace (and not attached):
[1] Rcpp_1.0.1 fansi_0.4.0 utf8_1.1.4 crayon_1.3.4 assertthat_0.2.1 R6_2.4.0
[7] magrittr_1.5 pillar_1.3.1 cli_1.1.0 rlang_0.3.4 rstudioapi_0.10 tools_3.5.3
[13] glue_1.3.1 compiler_3.5.3 pkgconfig_2.0.2 tidyselect_0.2.5 tibble_2.1.1