【问题标题】:How to select increasing values from two vectors - 'weaving two vectors'如何从两个向量中选择增加的值 - '编织两个向量'
【发布时间】:2018-06-18 20:22:58
【问题描述】:

我有两个不同长度的向量。两个向量都有顺序的值:

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 的第一个元素开始,我想在两个向量之间交替,并一次从每个向量中选择一个元素。要选择的每个后续值都应大于前一个值。

“编织”两个向量后的所需序列:

c(1, 2, 3, 7, 11, 14, 15)

因此,我们从 v1 中的第一个元素 (1) 开始。然后,下一个元素应该从v2中选择并且大于前一个选择的值;我们从 v2 (2 &gt; 1) 中选择 2。下一个值应该来自 v1 并且大于 2:我们从 v1 中选择 3。然后 7 来自 v2 (7 &gt; 3),11 来自 v1 (11 &gt; 7),依此类推,在向量之间交替,选取递增的值。

当 v2 中没有更多元素大于 v1 中的前一个值时,我们终止值的选择。因此,在这种情况下,15 是我们从 v1 中选择的最后一个值(丢弃了 16、17、18):


我更喜欢矢量化操作而不是不必要的循环。

额外:我的虚拟代码在 int 中。但我的实际数据是结构良好的时间值,我可以直接将其用作“lubridate”包中函数的参数。有什么功能可以完成这项工作吗?

Q1) 是否存在执行此操作的现有功能? Q2) 有没有办法以向量化的方式来做到这一点,而不是在每个循环之后循环和修剪输入向量?

【问题讨论】:

  • Q1 - 可能不是,这似乎是一个非常不寻常的操作。 Q2 - 可能不是矢量化方式。至少不是以可扩展的方式。下一次迭代取决于前一次操作的结果的操作通常是不可矢量化的。虽然“循环和修剪”听起来很糟糕(尤其是修剪部分),但我基本上会在一个 while 循环中遍历两个迭代器。
  • union,但如果你看一下代码,它只是unique(c(as.vector(x), as.vector(y)))
  • @Alexis OP 想要频繁跳过值,一般算法是 x 的第一个元素,y 的第一个元素到目前为止大于 max,x 的下一个元素大于 max 到目前为止,y 的下一个元素到目前为止大于 max... 比简单的 union 复杂得多。
  • 啊,是的,没有仔细阅读。
  • 当短向量用完,而长向量中还有几个更高的值时会发生什么?答案还有剩下的吗?还是只有第一个?还是最后一个?

标签: r sorting time


【解决方案1】:

看看这是否足够笼统:

# 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

【讨论】:

  • 嗨@Not-SoberCoder!我很想知道我的解决方案是否按您想要的方式工作。干杯
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多