这是一个小例子.在我的大数据集中,我有多年的数据,每组(div)的观察数量并不总是相等.
示例数据:
set.seed(1)
df<-data.frame(
year = 2014,
id = sample(LETTERS[1:26], 12),
div = rep(c("1", "2a", "2b"), each=4),
pts = c(9,7,9,3,7,5,3,7,2,7,7,1),
x = c(10,12,11,7,7,5,4,12,4,6,7,2)
)
Run Code Online (Sandbox Code Playgroud)
DF
# year id div pts x
#1 2014 G 1 9 10
#2 2014 J 1 7 12
#3 2014 N 1 9 11
#4 2014 U 1 3 7
#5 2014 E 2a 7 7
#6 2014 S 2a 5 5
#7 2014 W 2a 3 4
#8 2014 M 2a 7 12
#9 2014 L 2b 2 4
#10 2014 B 2b 7 6
#11 2014 D 2b 7 7
#12 2014 C 2b 1 2
Run Code Online (Sandbox Code Playgroud)
我想对这些数据进行排名,使得div 1中的个体排名高于div 2a/2b,并且在div 1中,个体根据'pts'的最高数量排名1,2,3,4,其次是'x'的最高数量".
div 2a和div 2b中的个体也应根据相同的标准单独排名.这看起来像这样:
df %>%
group_by(div) %>%
arrange(desc(pts), desc(x)) %>%
mutate(position = row_number(div))
# year id div pts x position
#1 2014 N 1 9 11 1
#2 2014 G 1 9 10 2
#3 2014 J 1 7 12 3
#4 2014 U 1 3 7 4
#5 2014 M 2a 7 12 1
#6 2014 E 2a 7 7 2
#7 2014 S 2a 5 5 3
#8 2014 W 2a 3 4 4
#9 2014 D 2b 7 7 1
#10 2014 B 2b 7 6 2
#11 2014 L 2b 2 4 3
#12 2014 C 2b 1 2 4
Run Code Online (Sandbox Code Playgroud)
但是,我想生成另一个等级的最终列/变量.这将使div 1中的所有个体都高于2a/2b,但2a/2b相等.即,2a/2b中的1个人现在应该获得5.5,排名2的个人现在应该获得7.5.所有年份在div2a和div2b中总有相同数量的个体.
它应该如下所示:
# year id div pts x position final
#1 2014 N 1 9 11 1 1.0
#2 2014 G 1 9 10 2 2.0
#3 2014 J 1 7 12 3 3.0
#4 2014 U 1 3 7 4 4.0
#5 2014 M 2a 7 12 1 5.5
#6 2014 E 2a 7 7 2 7.5
#7 2014 S 2a 5 5 3 9.5
#8 2014 W 2a 3 4 4 11.5
#9 2014 D 2b 7 7 1 5.5
#10 2014 B 2b 7 6 2 7.5
#11 2014 L 2b 2 4 3 9.5
#12 2014 C 2b 1 2 4 11.5
Run Code Online (Sandbox Code Playgroud)
我需要找到dplyr理想的解决方案.此外,它确实需要推广到'div1'中个体数量可能变化且div2a/div2b中个体数量变化的年份(尽管长度(div2a)==长度(div2b)总是如此).
我就是这样做的:
library(data.table)
dt = as.data.table(df)
dt[order(-pts, -x), rank.init := 1:.N, by = div]
dt[, div.clean := sub('(\\d+).*', '\\1', div)]
setorder(dt, div.clean, rank.init)
dt[, rank.final := mean(.I), by = .(div.clean, rank.init)]
setorder(dt, div, rank.final)
# year id div pts x rank.init div.clean rank.final
# 1: 2014 N 1 9 11 1 1 1.0
# 2: 2014 G 1 9 10 2 1 2.0
# 3: 2014 J 1 7 12 3 1 3.0
# 4: 2014 U 1 3 7 4 1 4.0
# 5: 2014 M 2a 7 12 1 2 5.5
# 6: 2014 E 2a 7 7 2 2 7.5
# 7: 2014 S 2a 5 5 3 2 9.5
# 8: 2014 W 2a 3 4 4 2 11.5
# 9: 2014 D 2b 7 7 1 2 5.5
#10: 2014 B 2b 7 6 2 2 7.5
#11: 2014 L 2b 2 4 3 2 9.5
#12: 2014 C 2b 1 2 4 2 11.5
Run Code Online (Sandbox Code Playgroud)
@ eddi的答案已经非常好了.我只是想frank()从开发版本中说明相同的使用函数data.table, v1.9.5,它可以计算向量,列表,data.frames或data.tables上的排名.
# from @eddi's
setDT(df)[, div.clean := sub('(\\d+).*', '\\1', div)]
df[, position := frank(.SD, -pts, -x, ties.method="first"), by=div]
df[, final := frank(.SD, div.clean, position, ties.method="average")]
Run Code Online (Sandbox Code Playgroud)
这也保留了原始订单,如果这是重要的.
我会把转换留给dplyr你.