通过分组对列进行R排名,以另一个变量为条件

时间:2015-03-15 12:13:38

标签: r

我有这样的数据框(df):

group col1 col2  
x      a    22    
x      a    23  
x      b    16  
x      b    18  
y      a    11  
y      a    12  
y      a    16  
y      a    45  
y      b    24  

所需的输出是:

group col1 col2 rank 
x      a    22  1  
x      a    23  2
x      b    16  0
x      b    18  0
y      a    11  1
y      a    12  2
y      a    16  3
y      a    45  4
y      b    24  0

即,

  • 按组和col1
  • 订购col2
  • 当col1 =“b”时,等级为0
  • 将col2的值从最小到最大排名

如何使用R来做到这一点?我会很高兴得到任何帮助。非常感谢。

3 个答案:

答案 0 :(得分:8)

你可以尝试

library(dplyr)
 df %>%
    group_by(group, col1) %>% 
    mutate(rank=replace(min_rank(col2), col1=='b',0) )
#    group col1 col2 rank
#1     x    a   22    1
#2     x    a   23    2
#3     x    b   16    0
#4     x    b   18    0
#5     y    a   11    1
#6     y    a   12    2
#7     y    a   16    3
#8     y    a   45    4
#9     y    b   24    0

如果您在有联系时不希望排名之间存在差距,请将min_rank替换为dense_rank

或者,而不是replace

 res <- df %>% 
          group_by(group, col1) %>% 
          mutate(rank=(col1!='b')*min_rank(col2))

 as.data.frame(res) #would be `data.frame`
 #    group col1 col2 rank
 #1     x    a   22    1
 #2     x    a   23    2
 #3     x    b   16    0
 #4     x    b   18    0
 #5     y    a   11    1
 #6     y    a   12    2
 #7     y    a   16    3
 #8     y    a   45    4
 #9     y    b   24    0

答案 1 :(得分:6)

或使用data.table v>= 1.9.5

library(data.table)
setDT(df)[, rank := frank(col2, ties.method = "dense"),
             by = .(group, col1)][col1 == "b", rank := 0L][]

#    group col1 col2 rank
# 1:     x    a   22    1
# 2:     x    a   23    2
# 3:     x    b   16    0
# 4:     x    b   18    0
# 5:     y    a   11    1
# 6:     y    a   12    2
# 7:     y    a   16    3
# 8:     y    a   45    4
# 9:     y    b   24    0

或者像@Arun建议的那样,如果您将b设置为零,则可以跳过一个分组步骤

dt[, rank := 0L][col1 != "b", rank := frank(col2, ties.method="dense"), by=group][]

答案 2 :(得分:5)

base R:

df$rank<-ave(df$col2,df[,1:2],FUN=rank)*(df$col1!="b")