创建多字段组排名

时间:2014-07-25 03:46:47

标签: r grouping ranking

对于以下简化数据框,我在每个测试中计算了每个州内每所学校的排名。问题是我的排名是连续的,我想在学校状态测试组中每次更改时重置它。

School<-rep(c("A","B","C","D"),each=10)
State<-rep(c("NY","NJ"),times=20)
Test<-rep(c("LSAT", "MCAT", "GRE","TOEFL","ACT"), times=8)
Grade<-trunc(rep((seq(from=500, to=600,length.out=4))))
dat<-data.frame(Test,State,School,Grade)

当我添加此排名逻辑时,

dat$rank <- NA
dat$rank[order(dat$Test,dat$State,dat$Grade)] <- 1:nrow(dat)
dat[order(dat$rank),]
View(dat[order(dat$rank),])

我的输出的前20行看起来像这样:

    Test State School Grade rank
10   ACT    NJ      A   533    1
30   ACT    NJ      C   533    2
20   ACT    NJ      B   600    3
40   ACT    NJ      D   600    4
5    ACT    NY      A   500    5
25   ACT    NY      C   500    6
15   ACT    NY      B   566    7
35   ACT    NY      D   566    8
18   GRE    NJ      B   533    9
38   GRE    NJ      D   533   10
8    GRE    NJ      A   600   11
28   GRE    NJ      C   600   12
13   GRE    NY      B   500   13
33   GRE    NY      D   500   14
3    GRE    NY      A   566   15
23   GRE    NY      C   566   16
6   LSAT    NJ      A   533   17
26  LSAT    NJ      C   533   18
16  LSAT    NJ      B   600   19
36  LSAT    NJ      D   600   20

我希望他们看起来像这样。请注意,决胜局是学校。如果学校A和学校C在ACT的新泽西州都有533的成绩,那么A学校将首先基于alpha-order。低分可以降低排名。

    Test State School Grade rank
10   ACT    NJ      A   533    1
30   ACT    NJ      C   533    2
20   ACT    NJ      B   600    3
40   ACT    NJ      D   600    4
5    ACT    NY      A   500    1
25   ACT    NY      C   500    2
15   ACT    NY      B   566    3
35   ACT    NY      D   566    4
18   GRE    NJ      B   533    1
38   GRE    NJ      D   533    2
8    GRE    NJ      A   600    3
28   GRE    NJ      C   600    4
13   GRE    NY      B   500    1
33   GRE    NY      D   500    2
3    GRE    NY      A   566    3
23   GRE    NY      C   566    4
6   LSAT    NJ      A   533    1
26  LSAT    NJ      C   533    2
16  LSAT    NJ      B   600    3
36  LSAT    NJ      D   600    4

我很欣赏有关如何在群体问题中处理此排名的指导。

4 个答案:

答案 0 :(得分:2)

使用dplyr

library(dplyr)
 dat%>%
 group_by(Test,State)%>%
 mutate(Rank=row_number())%>%
 arrange(Test,State, Rank) %>%
 head()
#       Test State School Grade Rank
#    1  ACT    NJ      A   533    1
#    2  ACT    NJ      C   533    2
#    3  ACT    NJ      B   600    3
#    4  ACT    NJ      D   600    4
#    5  ACT    NY      A   500    1
#    6  ACT    NY      C   500    2

答案 1 :(得分:1)

除非我遗漏了某些东西,否则这似乎是从plyr使用ddply的好时机

library(plyr)

ddply(dat, .(Test, State), transform,
      myrank = rank(Grade, ties.method="first"))

返回正确的排名顺序。您可以根据需要对数据框进行排序。

答案 2 :(得分:0)

您可以使用ave来排名。例如,你可以做

rankFirst <- function(x) rank(x, ties="first")
dat$Rank <- with(dat, ave(Grade, Test, State, FUN=rankFirst))

如果您想按字母学校名称打破关系,您可能希望先按学校对数据框进行排序以确保结果

dat <- dat[order(dat$School), ]
dat$Rank <- with(dat, ave(Grade, Test, State, FUN=rankFirst))

averankties="first"应该处理其他所有事情

答案 3 :(得分:0)

与MrFlick几乎相同,但我要指出有一个名为rank的R函数,它将通过平均order的结果来处理联系:

> dat$rank <- with(dat, ave(Grade, Test, State,  FUN=order) )
> dat$avgrank <- with(dat, ave(Grade, Test, State,  FUN=function(x) rank(x)) )
> dat[ order(dat$Test, dat$State, dat$rank) , ]
    Test State School Grade rank avgrank
10   ACT    NJ      A   533    1     1.5
30   ACT    NJ      C   533    2     1.5
20   ACT    NJ      B   600    3     3.5
40   ACT    NJ      D   600    4     3.5
5    ACT    NY      A   500    1     1.5
25   ACT    NY      C   500    2     1.5
15   ACT    NY      B   566    3     3.5
35   ACT    NY      D   566    4     3.5
28   GRE    NJ      C   600    1     3.5
8    GRE    NJ      A   600    2     3.5
38   GRE    NJ      D   533    3     1.5
18   GRE    NJ      B   533    4     1.5
23   GRE    NY      C   566    1     3.5
3    GRE    NY      A   566    2     3.5

如果有人知道为什么会失败,我会全力以赴:

> dat$avgrank <- with(dat, ave(Grade, Test, State,  FUN=rank) )
Error in get(as.character(FUN), mode = "function", envir = envir) : 
  object 'FUN' of mode 'function' was not found