我有这样的数据框(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
即,
如何使用R来做到这一点?我会很高兴得到任何帮助。非常感谢。
答案 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")