根据另一列的排名,在R中向数据框添加一列

6
这里是一个可以重现的数据示例。对于以下数据框:
df <- data.frame(Subject = c('John', 'John', 'John', 'John','Mary', 'Mary', 'Mary', 'Mary'),
                 SNR = c(-4,-4,0,4,0,4,4,8))

我想添加一列“rank”,根据主题为SNR提供排名,以便它看起来像这样:
Subject   SNR   Rank
John      -4    1
John      -4    1
John       0    2
John       4    3
Mary       0    1
Mary       4    2
Mary       4    2
Mary       8    3

我尝试使用了:

dfNew <- transform(df, Rank = ave(SNR, Subject, FUN = function(x) rank(x, ties.method = "first")))

但是我得到了以下内容:
Subject   SNR   Rank
John      -4    1
John      -4    2
John       0    3
John       4    4
Mary       0    1
Mary       4    2
Mary       4    3
Mary       8    4   

我也尝试使用不同的ties.method选项,但没有给我想要的结果(即仅排名1-3)。任何帮助将不胜感激!

4
尝试使用dplyr::dense_rank进行操作。如果你不想使用包,只需使用两行基本R代码即可完成。 - Rich Scriven
2
function(x) as.numeric(factor(x)) 在您的尝试中可以起作用。或者只需使用 factor(x),因为 ave 函数会强制转换回 SNR 的类型。 - rawr
谢谢@rawr,解决了问题。 - Rmg
4个回答

2

使用基本R中的aggregatefactor

ag <- aggregate(SNR~Subject, df, function(x) as.numeric(factor(x)))
df$rank <- c(t(ag[,-1]))

  Subject SNR rank
1    John  -4    1
2    John  -4    1
3    John   0    2
4    John   4    3
5    Mary   0    1
6    Mary   4    2
7    Mary   4    2
8    Mary   8    3

2

另一个基于R的方法:

transform(df1, Rank = ave(SNR, Subject, FUN = function(x) cumsum(c(TRUE, head(x, -1) != tail(x, -1)))))

提供:

  Subject SNR Rank
1    John  -4    1
2    John  -4    1
3    John   0    2
4    John   4    3
5    Mary   0    1
6    Mary   4    2
7    Mary   4    2
8    Mary   8    3

如果您的数据框还没有排序,请先使用df1 <- df1[order(df1$SNR),]对其进行排序,以便此方法能够给出正确的结果。


1
有点脏,但似乎能工作:

library(dplyr)
df %>% group_by(Subject) %>% mutate(Rank = as.numeric(as.factor(SNR))) 

  Subject   SNR  Rank
   <fctr> <dbl> <dbl>
1    John    -4     1
2    John    -4     1
3    John     0     2
4    John     4     3
5    Mary     0     1
6    Mary     4     2
7    Mary     4     2
8    Mary     8     3

不是我的投票,但我猜想这是因为您不需要加载包来添加列。 - Rich Scriven
如果你不经常使用它,那么你需要加载dplyr。我觉得负评(不是我)是由于as.numeric(as.factor())。但仍然有点小题大做。 - infominer

1
library(dplyr)    
df %>%
     arrange(Subject, SNR) %>%
     group_by(Subject) %>%
     mutate(rank=dense_rank(SNR))

当然,感谢 @rich-scriven 提到了 dense_rank()


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接