我有一个时间因变量,表示为两个向量:时间向量(已排序)和这些时间的值向量。我想在由不同排序时间向量指定的不同时间对该变量重新采样。
在另一种语言中,我会同时遍历两个排序的时间向量。即从旧时间向量的开头进行线性搜索,直到找到最接近新时间向量中第一个元素的时间,然后从旧向量中的该点继续查找最接近新向量中第二个元素的时间等等。这给出了 O(n) 的解。
这里的关键是两个时间向量的长度不同,并且元素不是一对一配对的,所以像 map2 或 walk2 这样的东西不是我想要的。
我可以使用 for 循环实现同时行走(参见下面的代码),它可以工作,但速度很慢。我还有另一个更 R codey 的解决方案,但它是 O(n^2) 所以它最终也很慢。是否有一种 R 方法可以使用内部 R 实现来实现 O(n) 解决方案?
或者,是否有一个 R 函数可以用二分搜索替换我的 get_closest() ,这样至少它会是 O(nlogn) ?
根据我的搜索,我怀疑答案是“编写一个从 R 调用的 C 函数”,但我对 R 还很陌生,所以我想检查一下我是否遗漏了一些东西。
编辑:
我应该明确指出 new_times 中的值可能不存在于 old_times 中。我想在 old_times 中找到时间最接近 new_times 中每个条目的索引。在我的实际应用程序中,我将进行线性插值,但这个问题只是关于搜索最近的邻居。
library(tidyverse)
# input values given
old_times <- c(2, 4, 6, 8, 10, 12, 14, 16, 18, 20)
old_values <- c(3, 7, 6, 7, 8, 9, 7, 6, 4, 6)
new_times <- c(4.1, 9.6, 12.3, 17.8)
期望的输出是
new_values <- c(7, 8, 9, 4)
我的尝试
new_values <- rep(NA, length(new_times))
old_index <- 1
for (new_index in 1:length(new_times)) {
while (old_index < length(old_times) &&
old_times[old_index] < new_times[new_index]) {
old_index <- old_index + 1
}
# I could now do interpolation if the value of new_times is in between
# two values in old_times. The key is I have a correspondence that
# new_times[new_index] is close in time to old_times[old_index].
new_values[new_index] <- old_values[old_index]
}
# Here's an alternative way to do it that uses more R internals,
# but winds up being O(n^2).
# Get the index in old_times closest to new_time.
# This is O(n).
get_closest <- function(new_time, old_times) {
return(which.min(abs(new_time - old_times)))
}
# Call get_closest on each element of new_times.
# This is O(n^2).
new_indices <- unlist(map(new_times, get_closest, old_times))
# Slice the list of old values to get new values.
new_values2 <- old_values[new_indices]
最佳答案
我们可以使用匹配
old_values[match(new_times, old_times)]
# [1] 7 8 9 4
match(new_times, old_times)
返回“第一个参数在第二个参数中的(第一个)匹配位置的向量。”,即
# [1] 2 5 6 9
我们可以使用 [
使用此结果从 old_values
中提取所需的值。
我们还可以使用 %in%
返回一个 bool 向量
old_values[old_times %in% new_times]
感谢@Andrew
关于r - 在 R 中同时遍历向量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55600489/