【问题标题】:Creating multi-field group rankings创建多字段组排名
【发布时间】:2014-07-25 03:46:47
【问题描述】:

对于以下简化的数据框,我计算了每个州、每个测试中每个学校的排名。问题是我的排名是连续的,我想随着学校-州-测试组的每次变化而重置它。

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 顺序排在第一位。分数越低排名越低是可以的。

    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

如果您能获得有关如何处理此组内排名问题的指导,我将不胜感激。

【问题讨论】:

    标签: r grouping ranking


    【解决方案1】:

    使用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
    

    【讨论】:

    • 谢谢。你能评论一下你的 dplyr 方法和@jalapic 的 plyr 方法之间的区别吗?对于 R 新手来说,plyr 是一个更好/更简单的入门级包吗?
    • @user3614783。 dplyrplyr 的高级版本。它可以用于大型数据集,因为它更快。就个人而言,我更喜欢dplyr 的语法更容易理解。关于区别,jalapic 使用了rank 方法,我使用了row_number() 独有的dplyr 函数。对于新用户,我认为dplyr 的语法会更容易。我也可能错了:-)
    • 我阅读了cran.r-project.org/web/packages/magrittr/magrittr.pdf,但仍然不明白 %>% 在您编写的代码中的作用。
    【解决方案2】:

    除非我遗漏了什么,这似乎是从 plyr 使用 ddply 的好时机

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

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

    【讨论】:

      【解决方案3】:

      您可以使用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" 应该处理其他所有事情

      【讨论】:

      • 您是否先尝试了“裸”rankave
      • @BondedDust 是的。不喜欢默认的“tie”方法。
      • @BondedDust 如果我将列命名为“Rank”,我不会收到错误消息。如果将新列命名为“rank”并运行两次,我确实会收到错误消息。那是因为您在 dat 中创建名为“rank”的列,所以当您第二次运行它时,rank 正在解析为 dat 中的列,因为使用 with 而您没有 @来自函数调用的 987654333@ 让 R 知道你想要一个函数(这是我的 rank(x) 仍然有效)。因此,通过指定base::rank,您可以消除歧义。
      • with 函数的另一个陷阱。
      【解决方案4】:

      与 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
      

      【讨论】:

      • 您是否不小心在您的全局环境中创建了一个名为“rank”的对象?或者dat 中是否存在现有的“等级”?我没有遇到和你一样的失败。 (运行良好。)也许dat$avgrank &lt;- with(dat, ave(Grade, Test, State, FUN=base::rank) ) 会消除歧义
      • rank 是我的全局环境中的基本函数,(我没有名为“rank”的数据对象,尽管这无关紧要)但使用 base::rank 确实成功。有趣的是把它作为'rank' 也成功了
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-07-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-08
      • 2021-12-28
      • 1970-01-01
      相关资源
      最近更新 更多