group_by编辑多列上行之间的距离

zyfwsgd6  于 2022-12-20  发布在  其他
关注(0)|答案(1)|浏览(120)

我有下面的数据框架。

输入:

class   id  q1  q2  q3  q4
Ali     12  1   2   3   3
Tom     16  1   2   4   2
Tom     18  1   2   3   4
Ali     24  2   2   4   3
Ali     35  2   2   4   3
Tom     36  1   2   4   2

1.***班级***表示教师姓名,
1.***id***表示学生用户ID,
1.q1q2、***q3***和***q4***表示不同试题的分数

要求:

我对发现潜在的作弊案例很感兴趣。我假设如果学生在同一个班级,并且在不同的问题上有相似的分数,他们很可能作弊。为此,我想计算绝对距离或差异,按班级名称分组,跨多列,即所有的试题q1q2q3***和***q4。我希望将此信息存储在以下几个新列中:
1.* 差异 :对于给定的班级名称,它包含与所有其他学生的id的成对距离或差值。对于给定的班级名称,它将信息存储为(id1,id2 =差值)
1.
作弊 :此列列出基于先前创建的新列的任何id*,其中差异为零(或某个阈值)。这将是一个标记,用于警告教师其学生可能作弊。

class   id  q1  q2  q3  q4  difference                  cheating
Ali     12  1   2   3   3   (12,24 = 2), (12,35 = 2)    NA
Tom     16  1   2   4   2   (16,18 = 3), (16,36 = 0)    36
Tom     18  1   2   3   4   (16,18 = 3), (18,36 = 3)    NA
Ali     24  2   2   4   3   (12,24 = 2), (24,35 = 0)    35
Ali     35  2   2   4   3   (12,35 = 2), (24,35 = 0)    24
Tom     36  1   2   4   2   (16,36 = 0), (18,36 = 3)    16

使用dplyr有可能实现这一点吗?

相关帖子:

我已经尝试寻找相关的解决方案,但没有一个解决了我所面临的确切问题,
1.这篇文章计算所有行对之间的差异。它没有包含group_by的情况,而且解决方案非常慢:R - Calculate the differences in the column values between rows/ observations (all combinations)
1.这个例子使用stringdist()只比较两列,我需要多列的解决方案,并使用group_by()条件:Creating new field that shows stringdist between two columns in R?
1.下面的帖子将列中的初始值与它们之前的值进行比较:R Calculating difference between values in a column
1.这个函数将一列中的值与所有其他列中的值进行比较。我希望这样做,但要通过group_by()逐行执行:R Calculate the difference between values from one to all the other columns

数据输出()

为了您的方便,我共享数据dput():

structure(list(class = 
c("Ali", "Tom", "Tom", "Ali", "Ali", "Tom"), 
id = c(12L, 16L, 18L, 24L, 35L, 36L), 
q1 = c(1L, 1L, 1L, 2L, 2L, 1L), 
q2 = c(2L, 2L, 2L, 2L, 2L, 2L), 
q3 = c(3L, 4L, 3L, 4L, 4L, 4L), 
q4 = c(3L, 2L, 4L, 3L, 3L, 2L)), row.names = c(NA, -6L), class = "data.frame")

任何帮助将不胜感激!

2skhul33

2skhul331#

您可以尝试对数据进行聚类,例如使用hclust(),一旦计算并Map了相对距离,就可以在预期欺骗的阈值处切割树。
在这个例子中,我使用标准的dist()函数来计算差异,stringdist函数可能更好,或者可能有另一个选项可以尝试。

df<- structure(list(class = 
c("Ali", "Tom", "Tom", "Ali", "Ali", "Tom"), 
id = c(12L, 16L, 18L, 24L, 35L, 36L), 
q1 = c(1L, 1L, 1L, 2L, 2L, 1L), 
q2 = c(2L, 2L, 2L, 2L, 2L, 2L), 
q3 = c(3L, 4L, 3L, 4L, 4L, 4L), 
q4 = c(3L, 2L, 4L, 3L, 3L, 2L)), row.names = c(NA, -6L), class = "data.frame")

#apply the standard distance function
scores <- hclust(dist(df[ , 3:6]))

plot(scores)

#divide into groups based on level of matching too closely
groups <- cutree(scores, h=0.1)

#summary table
summarytable <- data.frame(class= df$class, id =df$id, groupings =groups)

#select groups with more than 2 people in them
suspectgroups <- table(groups)[table(groups) >=2]

potential_cheaters <- summarytable %>% filter(groupings %in% names(suspectgroups)) %>% arrange(groupings) 
potential_cheaters

这对于这个测试用例是有效的,但是对于更大的数据集,cutree()函数中的height可能需要调整,还要考虑按类分割初始数据集,以消除类之间匹配人的机会(当然取决于具体情况)。

相关问题