1

我有一个数据框,其中包含grade.equivalentscaled.score,都是数字。我想找到scaled.score所有学生的百分比或高于给定的学生的百分比grade.equivalent

例如,给定以下数据框:

df.ex <- data.frame(grade.equivalent=c(2.4,2.7,3.1,2.5,1.4,2.2,2.3,1.7,1.3,2.2),
scaled.score=c(187,277,308,268,236,305,298,246,241,138)
)

我想知道每一个grade.equivalent分数在 301 分或以上的学生中,有多少学生的分数超过 301 分grade.equivalent

为此,我执行了以下操作:

find.percent.basic <- function(cut.ge, data, cut.scaled.score){
df.sub <- subset(data, grade.equivalent >= cut.ge & !is.na(scaled.score))
denom <- nrow(df.sub)
df.sub <- subset(df.sub, scaled.score >= cut.scaled.score)
numer <- nrow(df.sub)
return(numer/denom)
}

grade.equivs <- unique(df.ex$grade.equivalent)
grade.equivs <- grade.equivs[order(grade.equivs)]

just.percs <- sapply(grade.equivs, find.percent.basic, data=df.ex, cut.scaled.score=301)

new.df <- data.frame(grade.equivalent=grade.equivs, perc=just.percs)

我打算将它包装在一个函数中并与 plyr 一起使用。

我的问题是,有没有更好的方法来做到这一点?看起来这可能是 r 的基本功能或我不知道的通用包。

感谢您的任何想法。

编辑澄清上面的代码产生以下结果,这是我正在寻找的:

grade.equivalent      perc
1              1.3 0.2000000
2              1.4 0.2222222
3              1.7 0.2500000
4              2.2 0.2857143
5              2.3 0.2000000
6              2.4 0.2500000
7              2.5 0.3333333
8              2.7 0.5000000
9              3.1 1.0000000

根据@DWin 的观察,第二次编辑澄清

4

2 回答 2

2

布尔值的平均值是真实的百分比,所以应该这样做:

mean(data$scaled.score >= cut.ss, na.rm=TRUE)

正如您的评论一样,是的,这正是您需要做的。我会选择scaled.score稍微不同的访问方式,但没有真正的区别。

gs <- sort(unique(df.ex$grade.equivalent))
ps <- sapply(gs, function(cut.ge) {
  mean(df.ex$scaled.score[df.ex$grade.equivalent>=cut.ge] >= 301, na.rm=TRUE)
})
data.frame(gs, ps)

#  gs        ps
# 1.3 0.2000000
# 1.4 0.2222222
# 1.7 0.2500000
# 2.2 0.2857143
# 2.3 0.2000000
# 2.4 0.2500000
# 2.5 0.3333333
# 2.7 0.5000000
# 3.1 1.0000000

我不认为这种方法可以很好地与plyr's split-apply-combine 方法一起使用,因为您不能将数据拆分为每个等效年级的离散子集,相反,某些行将出现在多个子集。

另一种选择是将分数(或整个数据框,如果需要)自己拆分为所需的部分,然后应用您想要的任何功能;这将是与 相同的方法plyr,但更多的是手动。

scores <- lapply(gs, function(x) df.ex$scaled.score[df.ex$grade.equivalent>=x])
sapply(scores, function(x) mean(x>301, na.rm=TRUE))

最后的选择是将它们按顺序排列,然后计算累积平均值,并删除重复的grade.equivalent值,就像这样。

df2 <- df.ex[rev(order(df.ex$grade.equivalent)),]
df2$perc <- cumsum(df2$scaled.score>301)/1:nrow(df2)
df2 <- df2[nrow(df2):1,c("grade.equivalent", "perc")]
df2[!duplicated(df2$grade.equivalent),]
于 2013-06-11T00:59:42.567 回答
0
 with(df.ex, tapply(scaled.score, INDEX=grade.equivalent, 
                   FUN=function(s) 100*sum(s>301)/length(s) ) )
#1.3 1.4 1.7 2.2 2.3 2.4 2.5 2.7 3.1 
#  0   0   0  50   0   0   0   0 100 
于 2013-06-11T01:18:06.137 回答