基于几个变量的排名

Rank based on several variables

这是一个小例子。在我较大的数据集中,我有多年的数据,每组的观察次数 (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)
)

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

我想对这些数据进行排名,使得 div 中 div 1 中的等同者排名高于 div 2a/2b,并且在 div 1 中dividuals 根据 'pts' 的最高数量排名 1、2、3、4,其次是 'x' 的最高数量。

Individuals in div 2a 和 div 2b 也应该根据相同的标准在dividually 中排名。这看起来像这样:

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

但是,我想生成另一个排名的最终 column/variable。这将使 div 1 中的所有 individuals 排名高于 2a/2b,但 2a/2b 是相等的。即在div2a/2b中排名第1的iduals现在应该得到5.5,在dividuals中排名2的现在应该得到7.5。在所有年份中,div2a 和 div2b 中的 individual 总是相等的。

它应该是这样的:

#   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

我需要找到一个理想的 dplyr 解决方案。此外,它确实需要推广到 'div1' 中 individuals 的数量可能变化并且 div2a/div2b 中 individuals 的数量变化的年份(尽管长度( div2a)==length(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

@eddi 的回答已经很好了。我只是想使用 data.table, v1.9.5 开发版本中的 frank() 函数来说明相同的情况,它可以计算向量、列表、data.frames 或 data.tables.[=14= 上的排名]

# 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")]

这也保留了原始顺序,如果这很重要的话。

我会把 dplyr 的转换留给你。