在R中的组内排名,具有特殊的NA处理

时间:2017-08-24 10:03:59

标签: r

我有一个这样的数据框:

df <- data.frame(
  A = rep(c("A", "B", "C", "D"), each = 3),
  B = rep(c("V1", "V2", "V3"), 4),
  C = c(1,2,3,5,2,NA,4,6,7,3,7,8)
)

# Output
   A  B  C
1  A V1  1
2  A V2  2
3  A V3  3
4  B V1  5
5  B V2  2
6  B V3 NA
7  C V1  4
8  C V2  6
9  C V3  7
10 D V1  3
11 D V2  7
12 D V3  8

我的目标是在列B中的值上显示按列C分组的排名。如果有NA值,则根本不应该是排名的一部分。 RANK列应填充NANULL或类似的内容。关系应以平均值结束。

结果如下:

   A  B  C RANK
1  A V1  1 4
2  A V2  2 3.5
3  A V3  3 3
4  B V1  5 1
5  B V2  2 3.5
6  B V3 NA NA
7  C V1  4 2
8  C V2  6 2
9  C V3  7 2
10 D V1  3 3
11 D V2  7 1
12 D V3  8 1

2 个答案:

答案 0 :(得分:3)

我们可以在'C'上按'B',rank进行分组,指定具有逻辑条件的i,以便仅从'C'中选择非NA元素并赋值({{1 }}):=值来创建'RANK'列。默认情况下,未使用的行(即NA)将在新列中为NA

rank

答案 1 :(得分:2)

使用baseR中的ave()函数对组C中的B值进行排名

第一种方法:( 第二种方法的改进版)信用:Henrik

df$Rank <- with(df, ave(C, B, FUN=function(x) rank(-x, na.last = "keep", 
                                               ties.method = "average")))

第二种方法:

df$Rank <- with(df, ave(C, B, FUN=function(x) rank(-x, ties.method = "average")))
df$Rank[is.na(df$C)] <- NA

两种方法的输出:

df

#    A  B  C Rank
# 1  A V1  1  4.0
# 2  A V2  2  3.5
# 3  A V3  3  3.0
# 4  B V1  5  1.0
# 5  B V2  2  3.5
# 6  B V3 NA   NA
# 7  C V1  4  2.0
# 8  C V2  6  2.0
# 9  C V3  7  2.0
# 10 D V1  3  3.0
# 11 D V2  7  1.0
# 12 D V3  8  1.0

最后,具有相同输出的dplyr方法

df %>% group_by(B)  %>%  mutate(rank = rank(-C, na.last = "keep", 
                                            ties.method = "average"))