计算r中的等级

时间:2014-05-07 23:42:49

标签: r

我正在计算课程的最终平均分。大约有500名学生,成绩被组织成.csv个文件。列标题包括:

Name, HW1, ..., HW10, Quiz1, ..., Quiz5, Exam1, Exam2, Final

每个都有不同的加权,这不应该是编程问题。但是,每个学生都会删除最低的2个HW和最低的测验。我怎么能在r中编程呢?请注意,为每个学生删除的HW /测验可能不同(即学生A有HW2,HW5,Quiz2掉线,学生B有HW4,HW8,Quiz1掉线)。

3 个答案:

答案 0 :(得分:3)

这是一个更简单的解决方案。 sum_after_drop函数采用向量x并降低i最低分数并总结其余分数。我们为数据集中的每一行调用此函数。 ddply对于这项工作来说太过分了,但要保持简单。您应该可以使用apply执行此操作,但必须将最终结果转换为数据框。

然后可以在dd2上执行实际成绩计算。请注意,将cut函数与breaks一起使用是从总分中获得字母成绩的简单方法。

library(plyr)
sum_after_drop <- function(x, i){
  sum(sort(x)[-(1:i)])
}

dd2 = ddply(dd, .(Name), function(d){
  hw = sum_after_drop(d[,grepl("HW", nms)], 1)
  qz = sum_after_drop(d[,grepl("Quiz", nms)], 1)
  data.frame(hw = hw, qz = qz)
})

答案 1 :(得分:2)

这是一个如何使用reshape2包和基本函数来处理它的草图。

#sample data
set.seed(734)
dd<-data.frame(
    Name=letters[1:20],
    HW1=rpois(20,7),
    HW2=rpois(20,7),
    HW3=rpois(20,7),
    Quiz1=rpois(20,15),
    Quiz2=rpois(20,15),
    Quiz3=rpois(20,15)
)

现在我将其转换为长格式并拆分字段名称

require(reshape2)
mm<-melt(dd, "Name")
mm<-cbind(mm,
    colsplit(gsub("(\\w+)(\\d+)","\\1:\\2",mm$variable, perl=T), ":",
    names=c("type","number"))
)

现在,我可以使用by()获取每个名称的data.frame并执行其余计算。在这里,我只放下最低的作业和最低的测验,我给作业重量为.2,并测试重量为.8(假设所有家庭作品价值15分,测验25分)。

grades<-unclass(by(mm, mm$Name, function(x) {
    hw <- tail(sort(x$value[x$type=="HW"]), -1);
    quiz <- tail(sort(x$value[x$type=="Quiz"]), -1);
    (sum(hw)*.2 + sum(quiz)*.8) / (length(hw)*15*.2+length(quiz)*25*.8)
}))
attr(grades, "call")<-NULL   #get rid of crud from by()
grades;

让我们检查一下我们的工作。看看学生&#34; c&#34;

   Name HW1 HW2 HW3 Quiz1 Quiz2 Quiz3
      c   6   9   7    21    20    14

他们的成绩应该是

((9+7)*.2+(21+20)*.8) / ((15+15)*.2 + (25+25)*.8) = 0.7826087

事实上,我们看到了

grades["c"] == 0.7826087

答案 2 :(得分:0)

以下是dplyr的解决方案。它按学生和作业类型对分数进行排名(即计算所有学生1作业的等级顺序等),然后筛选出最低的1(或2,或其他)。 dplyr的语法非常直观 - 您应该可以非常轻松地浏览代码。

# Load libraries
library(reshape2)
library(dplyr)

# Sample data
grades <- data.frame(name=c("Sally", "Jim"),
                     HW1=c(10, 9),
                     HW2=c(10, 5),
                     HW3=c(5, 10),
                     HW4=c(6, 9),
                     HW5=c(8, 9),
                     Quiz1=c(9, 5),
                     Quiz2=c(9, 10),
                     Quiz3=c(10, 8),
                     Exam1=c(95, 96))

# Melt into long form
grades.long <- melt(grades, id.vars="name", variable.name="graded.name") %.%
  mutate(graded.type=factor(sub("\\d+","", graded.name)))
grades.long

# Remove the lowest scores for each graded type
grades.filtered <- grades.long %.%
  group_by(name, graded.type) %.%
  mutate(ranked.score=rank(value, ties.method="first")) %.%  # Rank all the scores
  filter((ranked.score > 2 & graded.type=="HW") |  # Ignore the lowest two HWs
         (ranked.score > 1 & graded.type=="Quiz") |  # Ignore the lowest quiz
         (graded.type=="Exam"))
grades.filtered

# Calculate the average for each graded type
grade.totals <- grades.filtered %.%
  group_by(name, graded.type) %.%
  summarize(total=mean(value))
grade.totals

# Unmelt, just for fun
final.grades <- dcast(grade.totals, name ~ graded.type, value.var="total")
final.grades

从技术上讲,您可以将summarize(total=mean(value))添加到grades.filtered数据框,而不是制作单独的grade.totals数据框 - 出于教学原因,我将它们分成多个数据框。