我有两个不同长度的向量。两个向量都按顺序具有值:
v1 <- c(1:5, 11:18)
v2 <- c(2, 7, 8, 14)
v1
# [1] 1 2 3 4 5 11 12 13 14 15 16 17 18
v2
# [1] 2 7 8 14
从v1的第一个元素开始,我希望在两个向量之间 alternate ,并一次从每个向量中选择一个元素。要选择的每个后续值应大于前一个值。
“编织”两个载体后的所需序列:
c(1, 2, 3, 7, 11, 14, 15)
因此,我们从v1中的第一个元素(1
)开始。然后,应从v2 中选择下一个元素,并且大于前面选择的值;我们从v2(2
)中选择2 > 1
。下一个值应该来自v1并且大于2
:我们从v1中选择3
。然后来自v2(7
)的7 > 3
,来自v1(11
)的11 > 7
,依此类推,在向量之间交替,选择不断增加的值。
当v2中没有更多元素大于v1中的前一个值时,我们终止值的选择。因此,在这种情况下,15
是我们从v1中选择的最后一个值(16,17,18被丢弃):
我更喜欢矢量化操作而不是不必要的循环。
额外:我的虚拟代码是int。但我的实际数据是结构良好的时间值,我可以直接用作'lubridate'包中函数的参数。是否有任何功能可以完成这项工作?
Q1)是否存在执行此功能的现有功能? Q2)有没有办法在矢量化方法中执行此操作,而不是在每个循环后循环和修整输入向量?
答案 0 :(得分:0)
看看这是否足够通用:
# extend the shorter of the two vectors, bind them to a matrix,
m <- cbind(v1, v2[1:length(v1)])
# 'weave' the two vectors and bind with a vector index
m2 <- cbind(c(t(m)), 1:2)
# remove NA and duplicates
m3 <- m2[!is.na(m2[ , 1]) & !duplicated(m2[ , 1]), ]
# order
m3 <- m3[order(m3[ , 1]), ]
# to pick values from every other vector,
# create a run-length id based on the vector index,
# remove duplicates of it, and use as index
m3[!duplicated(cumsum(c(1L, m3[ , 2][-nrow(m3)] != m3[ , 2][-1]))), 1]
# [1] 1 2 3 7 11 14 15
同样的想法,但data.table
:
library(data.table)
m <- cbind(v1, v2[1:length(v1)])
d <- data.table(v = c(t(m)), g = 1:2)
d2 <- d[!is.na(v) & !duplicated(v), ]
setorder(d2, v)
d2[ , .SD[1], by = rleid(g)]$v
# [1] 1 2 3 7 11 14 15