我正在计算一系列选择题考试的项目统计数据。我有一个使用mapply的解决方案,它在技术上是有效的,但它需要几个小时来计算一个更复杂的统计数据。我拥有的第一个数据集包括每个学生在每个评估中回答的每个问题的单独行。
df <- data.frame(c(rep("s1", 5), rep("s2", 5), rep("s3", 5),rep("s4", 5)),"a1", c("i1", "i2", "i3", "i4", "i5"), c(1, 0), 1)
colnames(df) <- c("student", "assessment", "item", "score", "points.possible")我做的第一步(并且只做一次)是创建一个包含所有唯一项的表。在这种情况下,这将是简单的,因为只有一个评估和5个项目。
unique <- subset(df[,c("assessment", "item")], !duplicated(df[,c("assessment", "item")]))然后,我需要为这些项目中的每一个计算一个统计数据。然而,棘手的部分是,计算需要计算学生在整个评估中获得的总分。下面是我为此编写的函数。
fun1 <- function(a.id, i.id) {
# subset original dataframe for just one assessment
subsetdf <- df[df$assessment == a.id,]
# generate list of students that got the item right and wrong
correct <- subsetdf$student[subsetdf$item==i.id & subsetdf$score==1]
wrong <- subsetdf$student[subsetdf$item==i.id & subsetdf$score==0]
# scores by student
scores <- aggregate(score ~ student, data=subsetdf,sum)/aggregate(points.possible ~ student, data=subsetdf, sum)
# average scores for students that got item right/wrong
x.1 <- sum(subsetdf$score[subsetdf$student %in% correct])/sum(subsetdf$points.possible[subsetdf$student %in% correct])
x.0 <- sum(subsetdf$score[subsetdf$student %in% wrong])/sum(subsetdf$points.possible[subsetdf$student %in% wrong])
# percent of students that got item right
p <- length(correct)/(length(correct)+length(wrong))
# final stat calculation
r <- ((x.1-x.0)*sqrt(p*(1-p)))/sd(scores[,2])
print(r)
}然后,我使用mapply在整个原始数据集上循环此函数,同时使用较小的数据集作为输入。
unique$r <- mapply(fun1, unique$assessment, unique$item)我很高兴我能够让它工作,但当我使用较大的数据集( "df“约700万行,”唯一“约2000行)时,需要相当长的时间(几个小时)。有没有其他更有效的方法来解决这个问题的建议?我了解到一个问题是,我的函数在每次循环时都会创建原始大型数据集的副本,但如果没有它,我不知道如何解决这个问题。
我仍然认为我自己是R的这种用法的初学者,所以任何建议都会非常感谢!
发布于 2015-04-02 05:46:27
当你表演的时候
scores <- aggregate(score ~ student, data=subsetdf,sum)/aggregate(points.possible ~ student, data=subsetdf, sum) 结果不是严格的数字,结果是一个数据框(例如,对于a.id = 'a1', i.id = 'i1'):
> aggregate(score ~ student, data=subsetdf,sum)
student score
1 s1 3
2 s2 2
3 s3 3
4 s4 2因此,当您将两者相除时,'s1'/'s1'的结果不是数字,并抛出一个警告。
correct和wrong。将该列的值作为一个指示器,告诉您该学生是对还是错。相反,请执行以下操作:
scores <- aggregate(subsetdf[,c('score', 'points.possible')], by = list(subsetdf$student), sum)
names(scores) <- c('student', 'score','points.possible')
scores$avg.score <- scores$score/scores$points.possible我也会为x.0和x.1做同样的事情。如果您通过i.id创建了一个子集,然后聚合了该数据帧的子集,那么还可以节省一些步骤。为每个学生检查他们是在correct中还是在wrong中(对于score和points.possible)两次,这也是非常昂贵的。
https://stackoverflow.com/questions/29355310
复制相似问题