通过学生尝试总结重复的项目

Summarizing repeated items by student attempt

预期输出的问题和解释

我有关于每个学生在考试中尝试了多少次以及他们回答了哪些项目的原始数据 (input)。对于这个例子,我有一个包含 5 个项目的池,但学生只对其中的 3 个项目做出回应。他们可以多次参加考试。因此,我想以一种可以看到以下所有信息的方式总结原始数据:

输入

作为input,我有原始数据,有学生nametrial的人数(例如,1,2,3...),以及所有池中的项目 i1:i5。项目 (0, 1) 的值显示学生是对还是错(1 = 正确,0 = 错误)。缺失值表明学生在那次尝试中没有拿走那个项目。

library(dplyr)

df <- tibble(name  = c("John", "John", "Mary", "Mary"),
             trial = c(1,  2,  1,  2),
             i1    = c(1,  0,  0,  NA),
             i2    = c(NA, NA, 1,  1),
             i3    = c(NA, 1,  NA, 1),
             i4    = c(0,  1,  1,  NA),
             i5    = c(0,  NA, NA, 1))

# # A tibble: 4 × 7
#   name  trial    i1    i2    i3    i4    i5
# <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
# 1 John      1     1    NA    NA     0     0
# 2 John      2     0    NA     1     1    NA
# 3 Mary      1     0     1    NA     1    NA
# 4 Mary      2    NA     1     1    NA     1

预期输出

作为 output,我想在下面看到像这样的摘要 table,显示我在上面的描述中提出的所有要点。我已经手动创建了这个 table,现在我试图用函数来组织它,这样我就可以加快这个过程。我的主要问题是生成列 repeatedrepeated_items。每个学生的第一次试验总是 repeated_itemsNArepeated 为零,因为这是第一次试验,所以他们以前从未见过这些项目。

我们可以使用

library(dplyr)
library(stringr)
library(tidyr)
df %>% 
  pivot_longer(cols = starts_with("i"),
     names_to = "i",values_drop_na = TRUE) %>%
  add_count(name, i, name = "n1") %>%
  mutate(i =replace(i, n1 <2, NA_character_)) %>%
  group_by(name, trial) %>% 
  summarise(correct = sum(value), n_items = n(),
     percent = mean(value), repeated= n_distinct(i, na.rm = TRUE), 
    repeated_items = str_c(i[!is.na(i)], collapse = ", "),
      .groups = 'drop_last') %>% 
  mutate(across(starts_with('repeated'), ~ replace(.x, 1, NA)))

-输出

# A tibble: 4 × 7
# Groups:   name [2]
  name  trial correct n_items percent repeated repeated_items
  <chr> <dbl>   <dbl>   <int>   <dbl>    <int> <chr>         
1 John      1       1       3   0.333       NA <NA>          
2 John      2       2       3   0.667        2 i1, i4        
3 Mary      1       2       3   0.667       NA <NA>          
4 Mary      2       3       3   1            1 i2    
library(tidyverse)

df %>% 
  mutate(correct = rowSums(across(starts_with("i")), na.rm = T),
         n_items = rowSums(!is.na(across(starts_with("i")))),
         percent = correct / n_items) %>% 
  group_by(name) %>% 
  mutate(repeated_items = across(starts_with("i")) %>% 
           imap_chr(~ ifelse(!is.na(diff(.)), .y, NA)) %>% 
           na.omit() %>% 
           str_flatten(","), 
         repeated_items = ifelse(row_number() == 1, NA, repeated_items),
         repeated = replace_na(str_count(repeated_items, ",") + 1, 0)) %>% 
  ungroup()

输出

  name  trial    i1    i2    i3    i4    i5 correct n_items percent repeated_items repeated
  <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>   <dbl>   <dbl>   <dbl> <chr>             <dbl>
1 John      1     1    NA    NA     0     0       1       3   0.333 NA                    0
2 John      2     0    NA     1     1    NA       2       3   0.667 i1,i4                 2
3 Mary      1     0     1    NA     1    NA       2       3   0.667 NA                    0
4 Mary      2    NA     1     1    NA     1       3       3   1     i2                    1