我有一个无序向量v
,就像下面显示的那样,希望找到列表中每个唯一元素的最后一次出现的索引。
v <- scan(text="1 2 1 2 1 1 1 3 1 2 2 3 3 3 1 1 1 4 1 1 1 4 1 5 5 6
6 2 3 3 4 4 2 2 2 2 2 3 3 3 1 4 4 4 3 2 5 5 5 5")
v
# [1] 1 2 1 2 1 1 1 3 1 2 2 3 3 3 1 1 1 4 1 1 1 4 1 5 5 6 6 2 3 3 4 4 2 2 2 2 2 3 3 3
# [41] 1 4 4 4 3 2 5 5 5 5
预期结果(按1、2、3、4、5的顺序):
41 46 45 44 50
我知道我可以使用unique(unlist(v))
来找到唯一的元素,但是如何找到它们最后出现的索引呢?有什么想法吗?
提前谢谢。
发布于 2015-01-06 23:31:55
另一种即使数据没有排序也有效的方法:
length(v1)-match(unique(v1),rev(v1))+1
发布于 2015-01-07 00:24:42
tapply(seq_along(v), v, max)
# 1 2 3 4 5 6
# 41 46 45 44 50 27
发布于 2015-01-06 23:19:11
如果vector
已经订购,您可以尝试rle
。提取长度($lengths)
,然后提取cumsum
。正如我前面提到的,如果没有订购,这将不起作用(同样,这取决于你真正想要的)。基本上,rle
通过检查拉伸上相似的连续元素的数量来工作。它将在列表中给出lengths
和相应的values
。
cumsum(rle(v1)$lengths)
#[1] 28 37 42 46 50
另一种选择是按向量对序列进行分组,并获取每个group
的max
值。我认为这是一个缓慢的过程。
unname(cumsum(tapply(seq_along(v1),v1, FUN=which.max)))
#[1] 28 37 42 46 50
或者只检查前一个值与当前值是否相同,然后插入TRUE
作为最后一个元素,用which
得到TRUE
的索引
which(c(v1[-1]!=v1[-length(v1)],TRUE))
#[1] 28 37 42 46 50
或者使用match
c(match(unique(v1),v1)-1, length(v1))[-1]
#[1] 28 37 42 46 50
或者使用findInterval
findInterval(unique(v1), v1)
#[1] 28 37 42 46 50
更新
对于新的矢量v2
max.col(t(sapply(unique(v2), `==`, v2)),'last')
#[1] 41 46 45 44 50 27
或者在ordering
无序向量之后使用findInterval
的函数
f1 <- function(v){
v1 <- setNames(v, seq_along(v))
ind <- order(v1)
as.numeric(names(v1[ind][findInterval(unique(v1), v1[ind])]))
}
f1(v2)
#[1] 41 46 45 44 50 27
使用@Marat talipov的帖子中的示例(z
),
f1(z)
#[1] 4 5 3
注意:我按照唯一元素首次出现在z
中的顺序得到结果。即1
,然后是3
、2
。如果需要根据值重新排序,可以使用order
(如@Marat Talipov所述)来完成。然而,在这种情况下,还不清楚OP真正想要什么。
数据
v1 <- c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3,
3, 4, 4, 4, 4, 5, 5, 5, 5)
v2 <- c(1, 2, 1, 2, 1, 1, 1, 3, 1, 2, 2, 3, 3, 3, 1, 1, 1, 4, 1, 1,
1, 4, 1, 5, 5, 6, 6, 2, 3, 3, 4, 4, 2, 2, 2, 2, 2, 3, 3, 3, 1,
4, 4, 4, 3, 2, 5, 5, 5, 5)
z <- c(1, 3, 2, 1, 3)
https://stackoverflow.com/questions/27801589
复制相似问题