我有一些数据:
test <- data.frame(A=c("aaabbb",
"aaaabb",
"aaaabb",
"aaaaab",
"bbbaaa")
)
等等。所有元素都是相同的长度,并且在我得到之前已经排序。
我需要建立一个新的行列,“第一”,“第二”,“第三”,之后的任何内容都可以留空,并且需要考虑关系。所以在上面的例子中,我想获得以下输出:
A B
aaabbb First
aaaabb Second
aaaabb Second
aaaaab Third
bbbaaa
bbbbaa
我查看了rank()和其他一些使用它的帖子,但我无法让它去做我想要的。
答案 0 :(得分:3)
这个怎么样:
test$B <- match(test$A , unique(test$A)[1:3] )
test
A B
1 aaabbb 1
2 aaaabb 2
3 aaaabb 2
4 aaaaab 3
5 bbbaaa NA
6 bbbbaa NA
执行此操作的众多方法之一。可能不是最好的,但是很容易让人想起并且相当直观。您可以使用unique
,因为您收到了预先排序的数据。
在对数据进行排序时,另一个值得考虑的合适函数是rle
,尽管在这个例子中它稍微有些迟钝:
rnk <- rle(as.integer(df$A))$lengths
rnk
# [1] 1 2 1 1 1
test$B <- c( rep( 1:3 , times = rnk[1:3] ) , rep(NA, sum( rnk[-c(1:3)] ) ) )
rle
计算向量中相等值运行的长度(以及我们并不真正关心的值) - 所以这也是有效的,因为您的数据已经被排序了。
如果你没有 在排名第三的项目之后有空白它甚至更简单(也更可读):
test$B <- rep(1:length(rnk),times=rnk)
答案 1 :(得分:3)
这似乎是一个很好的应用因素:
test$B <- as.numeric(factor(test$A, levels = unique(test$A)))
cumsum
也会浮现在脑海中,每当值发生变化时我们都会添加1
:
test$B <- cumsum(c(TRUE, tail(test$A, -1) != head(test$A, -1)))
(就像@Simon说的,有很多方法可以做到这一点......)