我有一个包含列grade.equivalent和scaled.score的数据框,这两个列都是数字。我想找出所有达到或超过每个grade.equivalent的学生在给定scaled.score或以上的学生的百分比。
例如,给定以下数据帧:
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,在所有达到或超过该grade.equivalent分数的学生中,有多少百分比的学生得分高于301。
为此,我执行了以下操作:
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的观察结果进行了第二次编辑以澄清
发布于 2013-06-11 08:59:43
布尔值的平均值是true的百分比,所以应该是这样的:
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的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-11 09:18:06
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 https://stackoverflow.com/questions/17034978
复制相似问题